0

以下代码显示出奇怪的行为。如果我按换行符给出输入,那么只有它打印直方图值,否则如果我直接输入 EOF(^Z),它会显示全零。getchar() 函数是否存在问题,它仅在按下换行符时才接受输入。

#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
#define MAXLEN 50
/* count lines, words, and characters in input */
main()
{
    int c, i, j, nc, state;
    int wordlength[MAXLEN];
    state = OUT;
    nc = 0;
    for (i = 0; i < MAXLEN; i++)
        wordlength[i] = 0;
    while ((c = getchar()) != EOF) {
        if (c == ' ' || c == '\n' || c == '\t') {
            if (state == IN) {
                wordlength[nc-1]++;
            }
            state = OUT;

        }
        else if (state == OUT) {
            //putchar('\n');
            state = IN;
            nc = 0;
        }
        if (state == IN)    {
            ++nc;
        }
    }

    for (j = 0; j < MAXLEN; j++)
            printf("\n%d - %d",j,wordlength[j]);

    for (i = 10; i >= 0; i--) {
        for (j = 0; j < MAXLEN; j++)
            printf(((wordlength[j] > i)?"|":" "));
        printf("\n");

    }

}
4

1 回答 1

1

您的代码或多或少对我有用,除非我在指示 EOF (Control-D在我的机器上;如果您使用Control-Z,它表明您在 Windows 上运行)之前键入一个没有后跟任何空格(空白、制表符、换行符)的输入单词. 如果您指示 EOF 没有最后的空格,则不会将最后一个单词添加到直方图中。当然,您还应该检查字长是否不太大,这样您就不会在wordlength数组之外进行索引(if (nc > MAXSIZE) nc = MAXSIZE;将所有非常长的字都计算为相同的大小)。

在主处理循环之后,您应该检查是否nc > 0增加wordlength.

也考虑使用isspace()from <ctype.h>

我尽可能使用enum而不是,以便在调试器中可以使用符号。#define你小心地避免了一个常见的错误;你把变量c变成了一个int,而不是一个char

#include <stdio.h>

enum { IN =  1, OUT = 0 };  /* inside, outside a word */
enum { MAXLEN = 50 };

/* count lines, words, and characters in input */
int main(void)
{
    int c, i, j, nc, state;
    int wordlength[MAXLEN];
    state = OUT;
    nc = 0;

    for (i = 0; i < MAXLEN; i++)
        wordlength[i] = 0;

    while ((c = getchar()) != EOF) 
    {
        if (c == ' ' || c == '\n' || c == '\t') 
        {
            if (state == IN) 
            {
                if (nc > MAXLEN)
                    nc = MAXLEN;    /* All long words grouped together */
                wordlength[nc-1]++;
            }
            state = OUT;
        }
        else if (state == OUT) 
        {
            state = IN;
            nc = 0;
        }
        if (state == IN)
            ++nc;
    }

    if (nc > 0)
    {
        if (nc > MAXLEN)
            nc = MAXLEN;    /* All long words grouped together */
        wordlength[nc-1]++;
    }

    for (j = 0; j < MAXLEN; j++)
        printf("\n%d - %d", j, wordlength[j]);

    for (i = 10; i >= 0; i--) 
    {
        for (j = 0; j < MAXLEN; j++)
            putchar( (wordlength[j] > i) ? '|' : ' ');
        printf("\n");
    }
    return 0;
}

你说你的机器有问题。对于声称在系统中发现错误,我会非常谨慎,尤其是在像getchar(). 我不能排除这种可能性,但这是我最不想指责的事情。在认为getchar().


在评论中,您要求被告知为什么您的程序无法在您的环境中运行。由于您尚未(尚未)正式确定运行程序的平台/环境,因此这是不可能的。

但是,我已经证明您发布的原始程序在类 Unix 环境中可以正常运行(我正在 MacOS X 10.7.2 上进行测试,但对于任何其他类似的类 Unix 系统都可以正常工作)。修改后的版本效果稍好一些;即使后面没有空格或换行符,它也会计算输入的最后一个单词。

如推断的那样,如果您在 Windows 上工作,那么终端 I/O 模型可能会有所不同。特别是,C 标准要求文本文件(可能包括终端输入)必须在 EOF 之前以换行符结尾;最后一个换行符之后的任何字符都可能被丢弃,但这取决于平台。二进制文件的行为是不同的。如果最后一个换行符之后的数据,那将与您报告的行为一致。这很可能是预期的行为 - 如果您查看未识别系统的文档。这是 PJ Plauger 在其出色的(但有些过时的)“标准 C 库”中确定的实现之间的差异之一。

但是,如果我的假设是正确的,那么我仍然希望明确说明您的代码是正确的(足够了);问题在于您的期望与记录在案的系统行为不符。请注意,报告您正在使用的平台有时至关重要。当您侵犯边缘情况时,它往往更加重要。而且您仍然极不可能遇到getchar().

顺便说一句,当我测试时,我需要输入Control-D两次(这正是我所期望的)。第一次将我在 ( abc) 行中输入的字符作为 3 字节读取刷新到程序中;第二个也将我输入的字符(全部为零)作为 0 字节读取刷新到程序中,然后由getchar(). 我还测试了abc(最后一个空白),然后是 EOF。您的代码不计入abc没有空格的;abc当它后面跟着一个空白时,它确实计算在内。

于 2012-02-07T14:52:16.317 回答