在二维数组中搜索字符组合的代码不输出任何内容

Code to search for combinations of characters in a two-dimensional array doesn't output anything

提问人:Someone Someone 提问时间:11/8/2023 最后编辑:Someone Someone 更新时间:11/10/2023 访问量:84

问:

如果此代码首先采用一行字符组合的输入,每个字符由空格分隔,然后不超过 10 行输入,所有输入的长度相等但不超过 10 个字符,然后从二维数组中的第一行搜索字符组合。这是代码。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#define WORDNUM 100
#define SIZE 10


int getWords(char wordMatrix[WORDNUM][100]){

    char c;
    int i=0, j=0;

    while ((c=fgetc(stdin)) != '\n'){
        if (isalpha(c)){
            wordMatrix[i][j]=c;
            j++;
        }
        else if(c==' '){
            i++;
            j=0;
        }
    }

    return i+1;
}


int getMatrix( char matrix[SIZE][SIZE]){

    char c;
    int i=0, j;

    while ((c=fgetc(stdin)) != EOF && i < (SIZE)){
        if (isalpha(c)){
            matrix[i][j]=c;
            j++;
        }
        else if(c=='\n'){
            i++;
            j=0;
        }
    }

    return i;
}


int checkExist(int rowM , int xM, int rowNum, int rowLen, char *word, char matrix[SIZE][SIZE]){
    int xW=1;
    int direction;

    direction = -1;
    while((rowM + direction) > 0){
        if(matrix[xM][rowM+direction] == word[xW]){
            xW++;

            if(xW == strlen(word)) return 1;

            else direction--;
            
        }

        else break;
    }

    direction = -1;
    while((xM + direction) > 0){
        if(matrix[xM+direction][rowM] == word[xW]){
            xW++;

            if(xW == strlen(word)) return 1;

            else direction--;
        }

        else break;
    }

    direction = 1;
    while((rowM + direction) < rowNum){
        if(matrix[xM][rowM+direction] == word[xW]){
            xW++;

            if(xW == strlen(word)) return 1;

            else direction++;
        }

        else break;
    }

    direction = 1;
    while((xM + direction) < rowLen ){
        if(matrix[xM+direction][rowM] == word[xW]){
            xW++;
            
            if(xW == strlen(word)) return 1;

            else direction++;
        }

        else break;
    }

    return 0;
}


int checkMatrix(int rowNum, int rowLen, char *word, char matrix[SIZE][SIZE]){

    int xM, rowM, check;

    for(rowM=0; rowM < rowNum; rowM++){
        for(xM=0; xM < rowLen; xM++){
            if(word[0] == matrix[rowM][xM]){
                if(strlen(word) == 1) return 1;
                else if (strlen(word)>1 && (check = checkExist(rowM, xM, rowNum, rowLen, word, matrix)) == 1) return 1;
            }
        }
    }

    return 0;
}


int main() {

    char word[WORDNUM][100], matrix[SIZE][SIZE];
    int logRowNumW, logRowNumM, logRowLen, rowW, x, check;

    logRowNumW = getWords(word);

    logRowNumM = getMatrix(matrix);

    logRowLen = strlen(matrix[0]);    

    for(rowW=0; rowW <logRowNumW; rowW++){
        if((check = checkMatrix(logRowNumM, logRowLen, word[rowW], matrix)) == 1){
            for(x=0; x<strlen(word[rowW]); x++){
                printf("%c", word[rowW][x]);
            }
        }
    }

    return 0;
}

问题是,它不会输出任何内容,无论是正确的还是不正确的,什么都没有。感谢您的任何建议

编辑:事实证明,两个愚蠢的错误是错误的。首先,xW ins在checkExist中没有重置每个方向,其次,我在checkExist中混淆了xM和rowM,它现在运行良好。

数组 C 多维数组

评论

3赞 Eric Postpischil 11/8/2023
编辑问题以提供重现问题的示例输入。
1赞 Weather Vane 11/8/2023
旁白:请注意,对于 with 应该 .我也感到困惑的是,你怎么能写出这么多代码,却不输出任何东西。分步推进工作,检查它是否按预期执行。char c;fgetc()int c;
1赞 0___________ 11/8/2023
strlen(word))是 UB,因为 u 不是 null 字符。word
0赞 hko 11/8/2023
该函数始终返回 0,并且您只打印 if 语句中的任何内容checkMatrix()if checkMatrix() == 1
0赞 Allan Wind 11/8/2023
如果输入包含前导空格,您也会遇到麻烦。您不执行任何边界检查(即小于 100)。getWords()

答:

2赞 Allan Wind 11/8/2023 #1
  1. getWords(), : 返回一个 (不是 ),当您检查 时,这一点尤为重要。getMatrix()fgetc()intcharEOFgetMatrix()

  2. getWords(), : 您不会以“\0”终止或终止,因此任何依赖于这些字符串(即)的东西都会触发未定义的行为。getMatrix()wordMatrixmatrixstrlen()

  3. getWords()可能应该跳过前导空格。

  4. getMatrix()您需要初始化 .j

  5. (不固定)为第二个 100 幻值引入一个MAX_WORD_LEN或类似值,并在遍历矩阵时使用该上限以避免缓冲区溢出。或者考虑使用动态分配输入空间。getline()

  6. (不固定)请考虑用于将字符串解析为单词。请注意,它会更改输入字符串,这需要做更多的工作,但可以用来定位分隔符,但您确实需要自己处理初始、连续和尾随分隔符。strtok()strpbrk()strch()

通过最初的 4 项更改:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#define WORDNUM 100
#define SIZE 10

int getWords(char wordMatrix[WORDNUM][100]){
    int c;
    int i=0, j=0;
    while ((c=fgetc(stdin)) != '\n') {
        if (isalpha(c)){
            wordMatrix[i][j]=c;
            j++;
        } if(c==' ') {
            if(!j) continue;
            wordMatrix[i][j] = '\0';
            i++;
            j=0;
        }
    }
    wordMatrix[i][j] = '\0';
    return i+1;
}


int getMatrix( char matrix[SIZE][SIZE]){
    int c;
    int i=0, j = 0;
    while ((c=fgetc(stdin)) != EOF && i < (SIZE)){
        if (isalpha(c)){
            matrix[i][j]=c;
            j++;
        }
        else if(c=='\n'){
            matrix[i][j] = '\0';
            i++;
            j=0;
        }
    }
    // If last line can be terminated with EOF instead of \n
    // then you need another '\0':
    // matrix[i][j] = '\0';
    return i;
}


int checkExist(int rowM , int xM, int rowNum, int rowLen, char *word, char matrix[SIZE][SIZE]){
    int xW=1;
    int direction;

    direction = -1;
    while((rowM + direction) > 0){
        if(matrix[xM][rowM+direction] == word[xW]){
            xW++;

            if(xW == strlen(word)) return 1;

            else direction--;

        }

        else break;
    }

    direction = -1;
    while((xM + direction) > 0){
        if(matrix[xM+direction][rowM] == word[xW]){
            xW++;

            if(xW == strlen(word)) return 1;

            else direction--;
        }

        else break;
    }

    direction = 1;
    while((rowM + direction) < rowNum){
        if(matrix[xM][rowM+direction] == word[xW]){
            xW++;

            if(xW == strlen(word)) return 1;

            else direction++;
        }

        else break;
    }

    direction = 1;
    while((xM + direction) < rowLen ){
        if(matrix[xM+direction][rowM] == word[xW]){
            xW++;
            if(xW == strlen(word)) return 1;
            else direction++;
        }
        else break;
    }
    return 0;
}


int checkMatrix(int rowNum, int rowLen, char *word, char matrix[SIZE][SIZE]){
    for(int rowM=0; rowM < rowNum; rowM++){
        for(int xM=0; xM < rowLen; xM++){
            if(word[0] == matrix[rowM][xM]){
                if(strlen(word) == 1) return 1;
                else if (strlen(word)>1 && (checkExist(rowM, xM, rowNum, rowLen, word, matrix) == 1)) return 1;
            }
        }
    }
    return 0;
}


int main() {
    char word[WORDNUM][100], matrix[SIZE][SIZE];
    int logRowNumW = getWords(word);
    int logRowNumM = getMatrix(matrix);
    int logRowLen = strlen(matrix[0]);
    for(int rowW=0; rowW <logRowNumW; rowW++){
        if((checkMatrix(logRowNumM, logRowLen, word[rowW], matrix)) == 1){
            for(int x=0; x<strlen(word[rowW]); x++){
                printf("%c", word[rowW][x]);
            }
        }
    }
    return 0;
}

您的程序现在生成输出:

a
ab
cd
<EOF>
a

在注释中使用提供的输入(我认为)是我编写硬编码测试用例并按照注释中讨论的行修改代码的方式:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#define N 10
#define NORTH {-1, 0}
#define EAST {0, 1}
#define SOUTH {1, 0}
#define WEST {0, -1}

int checkExist(int r, int c, int m, int n, const char *word, const char matrix[][N]) {
    if(word[0] != matrix[r][c])
        return 0;
    const int directions[][2] = { NORTH, EAST, SOUTH, WEST };
    for(int d = 0; d < sizeof directions / sizeof *directions; d++) {
        int w = 1;
        for(int r2 = r + directions[d][0], c2 = c + directions[d][1]; r2 >= 0 && r2 < m && c2 >= 0 && c2 < n && word[w]; r2 += directions[d][0], c2 += directions[d][1], w++)
            if(word[w] != matrix[r2][c2])
                break;
        if(!word[w])
            return 1;
    }
    return 0;
}

int checkMatrix(int m, int n, const char *word, const char matrix[][N]){
    for(int r=0; r < m; r++)
        for(int c=0; c < n; c++)
            if(checkExist(r, c, m, n, word, matrix))
                return 1;
    return 0;
}

int main(void) {
    char *word[] = {
        "oh",
        "to",
        "lot",
        "kol",
        "lok",
        "tol",
        "mol",
        "ho",
        "jol",
        "loj",
        "lol"
    };
    int words = sizeof word / sizeof *word;
    char matrix[][N] = {
        "john",
        "moto",
        "tolo"
    };
    int m = sizeof matrix / sizeof *matrix;
    int n = strlen(matrix[0]);
    for(int w=0; w < words; w++)
        if((checkMatrix(m, n, word[w], matrix)))
            printf("%s\n", word[w]);
}

这个非交互式程序返回:

oh
to
lot
tol
ho

我相信这是正确的输出。

如果匹配,那么也会。你可以预处理成一个数组,所以在上面。如果单词匹配,则还打印出相反的 if 为 true。word[w]reverse(word[w])wordstruct { char *word, int has_reverse }{ "oh", 1 }, { "to", 0 }, ...has_reverse

评论

0赞 Someone Someone 11/8/2023
谢谢你的建议。可悲的是,您提供的更改并没有多大帮助。现在它有时会起作用,但当它不起作用时,它就没有韵律或理由了。对于 oh to lot kol lok tol mol ho jol loj lol john moto tolo 它吐出到 lot tol ho ,对于 k kk kol lok lo ola ok ko okay kola 它唯一的输出是 k。我想我必须弄清楚你答案的第 5 点和第 6 点,并再次重写我的代码
1赞 Allan Wind 11/8/2023
我建议您接受答案,并在间歇性问题方面需要帮助时提出新问题。关键是要包含测试数据,一种特殊的强大方法是对失败的测试用例进行硬编码(在您提供的数据中,什么是单词,什么是矩阵?这样就消除了两个输入帮助程序函数,因为它们要么无关紧要,要么是根本原因。
0赞 Allan Wind 11/8/2023
5 和 6 可能与手头的问题无关。
0赞 Allan Wind 11/8/2023
在检查第一个字母是否匹配时,如果单词中有 1 个字母,则为特殊情况。我建议你把这个特殊情况,如果你愿意的话,推到.checkMatrix()checkExists()
0赞 Allan Wind 11/8/2023
checkExist()你有 essential 相同的代码重复 4 次。创建一个数组,其中包含要检查的每个方向 '{ {0, -1}, {0,1}, {-1,0}, {1, 0} }',然后遍历该数组。您唯一想要的调整是使用您现在拥有的类似代码检查行和列的上限和下限。