查找并列出字符串 C++ 中的所有字符簇

Posted

技术标签:

【中文标题】查找并列出字符串 C++ 中的所有字符簇【英文标题】:Find and list all char clusters in the string C++ 【发布时间】:2018-01-09 10:02:45 【问题描述】:

我正在寻找一些帮助来查找 C++ 中字符串中的所有字符簇。确切的任务是:

给定以下“二维字符串”(C++ 表达式):

string text =
  "#################aa##a###c######\n" +
  "####bbbbaaaabbbbbaaaaa###ccc##cc\n" +
  "#o##bbbbaaaabbbbbaaaaa###c#c##cc\n" +
  "#oo#bbbbaeeabbbbbbbbaa##cc#ccccc\n" +
  "#o##bbbbaeeabbbbbaaaaaa#cc#####c\n" +
  "#o##bbbbaaaabbbbbaaaaaa#cc#####c\n";

编写一个程序,计算相同 > 符号的每个连续区域的面积。如果两个相同的符号在一行或一列中相邻,则它们属于同一区域。不要计算换行符 (\n) 符号,它们只是为了 > 形成 2D 字符串。

main函数应该是递归的。

提示:使用一个额外的 2D 数组来标记 2D 字符串中的每个符号,如果它 > 已经被计算过。逐行扫描数组,直到找到尚未计数的符号 >。然后,从这个 >symbol 开始运行递归面积计算函数。继续,直到所有符号都标记为已计数。

程序输出应该(或多或少)如下所示:

Region of symbols #, area …
Region of symbols a, area …
Region of symbols #, area …
Region of symbols c, area …

我当前的代码如下所示:

#include <iostream>
#include <string>
using namespace std;

int cords (string str, int x, int y) 
    int length, i, position, lines = 0, x_max, y_max;
    char symbol;
    length = str.length();
    for (i = 0; i < length; i++) 
        symbol = str[i];
        if (symbol == '\n')
            lines++;
    
    length -= lines;
    x_max = length / lines;
    y_max = length / x_max;
    position = x - 1 + (y - 1) * x_max + y - 1;

    if (x <= x_max && y <= y_max)
        return position;


int clusterMiner (char symbol, string str, int x, int y, int counter, int last) 
    if (x > 32 || y > 6) 
        return counter;
     else 
        if (str[cords(str, x++, y)] == symbol) 
            counter++;
            return clusterMiner(symbol, str, x++, y, counter, x);
         else if (str[cords(str, 1, y++)] == symbol) 
            return clusterMiner(symbol, str, 1, y++, counter, x);
        
    


int main () 
    int length, lines, i, j, k, l, counter;
    string text = // 32 elements per line
    "#################aa##a###c######\n" // 32
    "####bbbbaaaabbbbbaaaaa###ccc##cc\n" // 64
    "#o##bbbbaaaabbbbbaaaaa###c#c##cc\n" // 96
    "#oo#bbbbaeeabbbbbbbbaa##cc#ccccc\n" // 128
    "#o##bbbbaeeabbbbbaaaaaa#cc#####c\n" // 160 
    "#o##bbbbaaaabbbbbaaaaaa#cc#####c\n"; // 192

    counter = clusterMiner('#', text, 1, 1, 0, 0);
    cout << counter;

    return 0;

Cords 函数只是为了更容易与字符串的二维交互。

我不确定下一步该做什么。现在程序只计算一些符号,因为它停在第一个不同的符号处,忽略了连接到其他节点的符号。

谢谢!

【问题讨论】:

只是一个小提示:无论您是否已经“访问”(即计算)某个角色,将其存储在某处可能会有所帮助。然后从每个字符中,您可以检查您尚未访问的所有 4 个相邻字符。注意边界,这样您就不会阅读文本之外的记忆。 【参考方案1】:

首先,不要一直新计算x_max和y_max,只做一次,存入一个变量。然后,您将不得不遍历整个字段:

char get(int x, int y)

    // + 1: the newline!!!
    return field[x + y * (x_max + 1)];


void countAll()

    calculateMaxima();
    // created your visited array now
    for(unsigned int y = 0; y <= y_max; ++y)
    
        for(int x = 0; x <= x_max; ++x)
        
            if(!visited[x, y])
            
                count = 0;
                search(get(x, y), x, y);
                // output count here...
            
        
    

每次我们击中一个尚未访问过的角色时,i。 e.一个新的,我们开始一个新的搜索。对于每次搜索,我们必须考虑每个当前位置x, y:x +/- 1, yx, y +/- (x_max + 1 的四个邻居(除了边缘的位置,它们的位置更少)。因此,您的搜索可能如下所示:

void visit(char symbol, int x, int y)

    if(!visited[x][y] && get(x, y) == symbol)
    
        ++count;
        ++visited[x][y] = true;
    
    search(symbol, x, y);


void search(char symbol, int x, int y)

    if(x > 0)
        visit(x - 1, y);
    if(x < max_x)
        visit(x + 1, y);
    if(y > 0)
        visit(x, y - 1);
    if(y < max_y)
        visit(x, y + 1);

现在,我假设 count、visited 和 x/y_max 是一些全局变量。 Cleaner,因为我们是 C++,会为此目的编写一个单独的类:

class ClusterMiner

    unsigned int count;
    std::string field;
    // ...

    void visit(char symbol, int x, int y);
    void search(char symbol, int x, int y);
    // ...
public:
    void countAll();
;

代码未经测试且不完整,它只会为您提供必要的提示以找到自己的方式......

旁注:如果您有相同字符的未连接区域,这些区域将被检测到。如果不希望这样做,您可以总结结果 e。 G。在std::map&lt;char, unsigned int&gt; 中,并在您完成计数后迭代这个...

【讨论】:

以上是关于查找并列出字符串 C++ 中的所有字符簇的主要内容,如果未能解决你的问题,请参考以下文章

C++编程,查找字符串子串并替换。

在 C++ 中查找传入字符串中的模式(包括像°这样的特殊字符)

使用 C++ 查找文件中的所有重复模式

查找并列出包含/不包含特定字符串的文件

如何列出当前目录下,以install开头的所有文件

在 C++ 中查找和比较 Unicode 字符