【问题标题】:unable to store all the words of a text in a character array无法将文本的所有单词存储在字符数组中
【发布时间】:2021-12-29 20:26:21
【问题描述】:

我想将文本中的单词存储在二维字符数组中,其中相同的单词只存储一次。问题是程序似乎没有存储最后几个单词。我已经包含了整个程序,因为我无法找出有问题的部分。 这是我的尝试:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define N 20
#define M 110

int main() { 
    char text[M], c[N][N], word[N];
    int i, j, k=0, l=0, d, v;

    for(i=0; i<N; i++) {
        for(j=0; j<N; j++) {
            c[i][j]='\0';
        }
    } 
    for(i=0; i<M; i++) {
        text[i]='\0';
    }    
    for(i=0; i<N; i++) {
        word[i]='\0';
    }    
    for(i=0; i<M; i++) {
        d=scanf("%c", &text[i]);  
        if(d==EOF) {
            text[i]='\0';
            break;
        }    
    }        
    for(i=0; i<strlen(text); i++) {    
        if(isspace(text[i])==0) {
            word[l]=tolower(text[i]);
            l++;
        }
        if((i==strlen(text)-1)||((isspace(text[i])!=0)&&(isspace(text[i+1])==0))) {    
            for(v=0; v<i; v++) {
                for(j=0; j<N; j++) {
                    if(word[j]!=c[v][j]) {
                        break;
                    }
                }
                if(j==N) {
                    l=0;
                    break;
                }
            }
            if(v==i) {  
                for(j=0; j<l; j++) { 
                    c[k][j]=word[j];
                }
                k++;
                l=0;
            }
        }
    }
    printf("\n\n");
    for(i=0; i<N; i++) { 
        for(j=0; j<N; j++) {
            printf("%c", c[i][j]);
        }    
        printf(" ");
    }        
    return 0;
}

对于某些输入,并非所有单词都被打印(不存储?)。 例如输入:a b c d e f g h i k l m n o pCtrl+D,输出为:a b c d e f g h i k

我注意到如果我增加N 并提供相同的输入,打印的字数也会增加。任何帮助将不胜感激。

编辑:

如果我们替换

for(v=0; v<i; v++)
for(j=0; j<N; j++)
//...
if(j==N)
//...
if(v==i)

for(v=0; v<k; v++)
for(j=0; j<l; j++)
//...
if(j==l)
//...
if(v==k)

程序正常运行。

【问题讨论】:

  • "I have included the whole program, because I can't figure out the problematic part." -- 您是否尝试过在调试器中逐行运行代码,同时监视所有变量的值,以确定您的程序在什么时候停止按预期运行?如果您没有尝试过,那么您可能想阅读以下内容:What is a debugger and how can it help me diagnose problems? 您可能还想阅读以下内容:How to debug small programs?
  • 即使使用调试器并不能真正解决问题,它至少应该可以帮助您隔离问题并创建问题的minimal reproducible example,这样其他人会更容易来帮你。大多数人不会愿意为你调试整个程序,因为那应该是你的工作。
  • 除了使用调试器之外,另一个技巧是使用有意义的变量名。在任何时候,您都有近 10 个单字母变量。这使得阅读和调试变得非常困难。
  • 除了@kaylum 所说的之外,将其分解为具有针对性的小功能将非常有帮助。虽然我承认你可能还没有在课堂上讲过这个。
  • @JohnKall: "I haven't used a debugger since I don't really know how to handle it yet." -- 那么这可能是改变这种状况的理想机会吗?如果您使用的是IDE,它可能具有内置调试器,或者可以轻松安装。如果您在没有 IDE 的情况下进行编译,那么您可能想要使用 GDB。您可以在 Google 中搜索GDB tutorial

标签: c output


【解决方案1】:

如何使用调试器查找错误

首先,为了让你在调试器中重新启动程序时不必输入一长串的输入,我建议你更换代码

for(i=0; i<M; i++) {
    d=scanf("%c", &text[i]);  
    if(d==EOF) {
        text[i]='\0';
        break;
    }    
} 

与:

strcpy( text, "a b c d e f g h i j k l m n o p" );

这样,您在问题中指定的输入将被硬编码到程序中,并且不再需要键盘输入。

如果您在调试器中运行程序,在关键位置设置断点,然后逐行运行程序,那么您会注意到在该行中

if(word[j]!=c[v][j]) {

变量v 有时具有值20。这是访问数组c 越界,因为有效索引只有019。这会导致未定义的行为,并导致您的程序错误地认为该单词已存在于数组中,因此它不会打印它。

如何修复错误

上一节描述的bug可能是因为那一行

for(v=0; v<i; v++) {

错了。变量v 应限制为N,而不是i。因此,您应该将该行更改为以下内容:

for(v=0; v<N; v++) {

如果你也换行

if(v==i) {

if(v==N) {

那么程序就有了预期的输出。

其他说明

还值得注意的是,您向输出流发送了近 400 个空字符。您的终端/控制台似乎忽略了它们而不是显示它们,但某些终端的行为可能有所不同。因此,您可能需要更改线路

for(i=0; i<N; i++) {
    for(j=0; j<N; j++) {
        printf("%c", c[i][j]);
    }
    printf(" ");
}

到以下:

for(i=0; i<N; i++) {
    printf("%s", c[i]);
    printf(" ");
}

这样,空字符将不会被发送到输出流。但是,如果这样做,则每个字符串中只能存储 19 个字符而不是 20 个字符,因为终止空字符现在需要一个额外的字节。您可能需要更改代码以强制执行此限制。

【讨论】:

  • 非常感谢您花时间解释!现在所有单词都已存储。我在初始代码中发现了一个逻辑错误:在错误行而不是 i 中,我想写 k 。这种变化似乎也解决了问题。
  • 不幸的是,还存在另一个问题:如果一个单词有多个字母,则下一个单词总是会再次被存储。例如a or a 打印a or a 而不是a or。我的问题已经得到解答,所以也许我会尝试自己调试它;)
  • 我做了一些更改,现在它可以正常工作了。再次感谢您的帮助。下次在问这样的问题之前,我会先使用调试器。
  • @JohnKall:我很高兴能够提供帮助。尽管我帮助您解决了当前的问题,但我相信您学到的最有价值的一课是如何使用调试器自己确定确切的问题。
猜你喜欢
  • 1970-01-01
  • 2017-03-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
  • 1970-01-01
  • 2016-03-07
相关资源
最近更新 更多