getchar()的行为是否适用于此程序?

时间:2012-02-07 14:46:29

标签: c getchar

以下代码显示奇怪的行为。如果我按下换行符给出输入,那么只打印直方图值,否则如果我直接输入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");

    }

}

1 个答案:

答案 0 :(得分:1)

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

在主处理循环之后,您应该检查是否nc > 0,如果是,请在wordlength中增加相应的条目。

也可以考虑使用isspace()中的<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()中存在错误之前,我会花很多时间来解决我做错的事情。


在评论中,您要求告诉您为什么您的程序无法在您的环境中运行。由于您尚未正式确定运行程序的平台/环境,因此无法实现。

但是,我已经证明了你原来的as-posted程序在类似Unix的环境中运行得相当合理(我正在MacOS X 10.7.2上进行测试,但对于任何其他类似的类Unix系统它都会起作用。 )。修订版略好一些;它将计算输入的最后一个单词,即使它后面没有空格或换行符。

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

然而,如果我假设的是正确的,那么我仍然希望明确你的代码是正确的(足够);问题在于您的期望与系统记录的行为不符。请注意,报告您正在使用的平台有时至关重要。当你正在侵占边缘案件时,它往往更为重要。你在getchar()中遇到一个错误的可能性极小。

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