用C语言打印字长直方图

用C语言打印字长直方图,c,arrays,for-loop,histogram,kernighan-and-ritchie,C,Arrays,For Loop,Histogram,Kernighan And Ritchie,好的,我用的是Kernighan和Ritchie的“C编程语言”,我在练习1.13,但我似乎不能正确理解这一点。我的程序似乎打印得不多。问题如下: 练习1-13。编写一个程序来打印输入中单词长度的直方图。用图形绘制直方图很容易 横杆;垂直方向更具挑战性 除了创建变量外,下面是我的伪代码,用于读取输入并存储我要存储在数组中的内容 创建一个数组——在本例中,我的数组大小为21(21个元素,从0到20),所有元素最初都被赋值为0。它有21个元素,因为我不会使用超过20个字符的单词。我意识到这很奇怪,因

好的,我用的是Kernighan和Ritchie的“C编程语言”,我在练习1.13,但我似乎不能正确理解这一点。我的程序似乎打印得不多。问题如下:

练习1-13。编写一个程序来打印输入中单词长度的直方图。用图形绘制直方图很容易 横杆;垂直方向更具挑战性

除了创建变量外,下面是我的伪代码,用于读取输入并存储我要存储在数组中的内容

  • 创建一个数组——在本例中,我的数组大小为21(21个元素,从0到20),所有元素最初都被赋值为0。它有21个元素,因为我不会使用超过20个字符的单词。我意识到这很奇怪,因为没有单词有零个字符
  • 开始计算输入中的字符数
  • 如果遇到空格、制表符或换行符(即,这表示第一个单词已结束),请停止
  • 根据单词的字符数,增加数组中的特定位置(即,如果单词有两个字符,则向数组中位置2处的元素添加1)
  • 递增wordCounter变量——该变量的名称表示该变量跟踪输入中已“读取”的字数
  • 继续对每个单词执行此操作,直到达到EOF
  • 这是我打印直方图(水平)的伪代码

  • 对于第一个位置,使用记号|打印存储在数组第一个位置(即0)中的值
  • 对数组中的每个元素执行此操作 这是我的密码:

    #include <stdio.h>
    
    #define SIZEOFWORDSOFLENGTH 21
    
    int main() {
        int wordsOfLength[SIZEOFWORDSOFLENGTH];
        int c, i, j;
        int lengthCounter = 0;
    
        /*Initializing all array elements to 0.*/
        for (i = 0; i < SIZEOFWORDSOFLENGTH; i++)
            wordsOfLength[i] = 0;
    
        /*Going through the input and counting.*/
        while ((c = getchar()) != EOF) {
            ++lengthCounter;
            if (c == ' ' || c == '\t' || c == '\n') {
                ++wordsOfLength[lengthCounter - 1];
                lengthCounter = 0;
            }
        }
    
        for (i = 0; i < SIZZEOFWORDSOFLENGTH; i++) {
            printf("Words of Length %d: ", i);
            /*The third argument of the following for loop was previously j = j*/
            for (j = 0; j < SIZEOFWORDSOFLENGTH; j++) {
                while (j < wordsOfLength[i]) {
                    printf("|");
                    /*Was previously j++ instead of break*/
                    break;
                }
            }
            printf("\n");
        }
    }
    
    #包括
    #定义SIZEOFWORDSOFLENGTH 21
    int main(){
    int-wordsOfLength[sizeofordsofLength];
    int c,i,j;
    int长度计数器=0;
    /*正在将所有数组元素初始化为0*/
    对于(i=0;i

    我手工调试过,但似乎找不到问题。也许有件很简单的事情发生在我的头上。另外,我知道以前有人问过这个问题,但我并没有试图找到解决实际问题的方法,我认为我的伪代码是正确的,如果不是有点正确的话,我只是想知道我的代码出了什么问题,也许可以学点东西。提前谢谢。

    您不需要从中的lengthCounter中减去'1'

    ++wordsOfLength[lengthCounter - '1'];
    
    应该是

    ++wordsOfLength[lengthCounter];
    
    如中所示,读取循环存在问题,因为它在数组
    wordsOfLength
    中使用了负索引。我会让生活变得简单,让
    wordsOfLength[I]
    存储长度
    I
    的字数,尽管这实际上浪费了
    wordsOfLength[0]
    。我会使用
    中的宏来发现单词边界,并记录我是否在单词中。使用
    intc
    可获得积分

    int inword = 0;
    while ((c = getchar()) != EOF)
    {
        if (!isspace(c))
            lengthCounter++;
        else if (inword)
        {
            wordsOfLength[lengthCounter]++;
            lengthCounter = 0;
            inword = 0;
        }
    }
    if (inword)
        wordsOfLength[lengthCounter]++;
    
    这段代码不会被文件中的空白所迷惑。如果你认为阅读“AntiDisesstablishmentarianism”(28)或“Floccinautinihilipilifilization”(29)或其他奇怪的长单词有任何风险,你应该检查
    lengthCounter
    ,然后盲目使用它作为索引,或者从计数中删除过长的单词,或者将它们全部映射到“20多个字符”类

    您的最终三重循环也很有问题-目前是:

    for (i = 0; i < SIZZEOFWORDSOFLENGTH; i++) {
        printf("Words of Length %d: ", i);
        /*The third argument of the following for loop was previously j = j*/
        for (j = 0; j < SIZEOFWORDSOFLENGTH; j++) {
            while (j < wordsOfLength[i]) {
                printf("|");
                /*Was previously j++ instead of break*/
                break;
            }
        }
        printf("\n");
    }
    

    现在唯一的问题是
    wordsOfLength
    中的最大值是否太长(例如,您已经阅读了莎士比亚的全部作品,因此其中一些单词出现了数千次)。

    感谢您的回复。比如说,我写了一些类似“嗨,我的名字叫雷内”的东西作为输入。在while循环的第三次迭代中,lengthCounter的值不是为3吗?既然第一个单词“Hi”的长度是2,我不需要减去1,使之成为[lengthCoutner-'1']。我将通过执行++wordsOfLength[lengthCounter-'1',增加数组的第二个位置;否?@ReneAlejandroSantiago:lengthCounter-'1'
    (在
    1
    周围加上单引号)的使用意味着您可能正在从长度中减去49。如果您编写了
    lengthCounter-1
    (在
    1
    周围没有单引号),您可能会有一个更好的参数。啊,对了,如果是这样的话,您需要减1,而不是“1”“1”是一个字符,而不是一个数字,当您在算术表达式中使用“1”时,它将转换为整数值49。@JonathanLeffler此特定程序依赖于数字的字符表示的属性。例如,测试if(c>='0'&&c@ReneAlejandroSantiago在c,1和'1'中的意思不同。如果运行以下代码打印(“%d\n”,(int)1);打印(“%d\n”,(int)'1'),可以看到差异;“1”是数字1的字符表示形式,实际上并不意味着数字1。您可以看到ASCII字符的值,请注意,您应该在
    wordsOfLength
    的声明中使用宏SizeOfOrdsOfLength。您应该查看如果文件中的第一个字符是空白、制表符或换行符会发生什么。@JonathanLeffler谢谢Jonathan,我忘了提到我假设没有前导空格、制表符或换行符。我还在word声明中包含了宏SIZEOFWORDSOFLENGTH
    for (i = 1; i < SIZZEOFWORDSOFLENGTH; i++)
    {
        printf("Words of Length %2d: ", i);
        for (j = 0; j < wordsOfLength[i]; j++)
            printf("|");
        printf("\n");
    }