K& R:第6章 - 为什么getword()函数不读取EOF?

时间:2011-12-15 02:36:35

标签: c eof

这是我关于Stack Overflow的第一篇文章,所以我希望我不会踩到任何人的脚趾。

当然,所有的输入都受到欢迎和赞赏,但那些最适合回答的人实际上会读到这本书, C Programming Language,2nd ed。

我刚刚完成了练习6-4的编码,但我似乎无法解决问题。为什么getword()函数在我按下Ctrl + D(我在Arch Linux VM中使用C代码)之前没有读取EOF?

本书以前的许多练习都需要从stdin中读取。我会这样做的一种方式是通过类似

的方式
while ((c = getchar()) != EOF) {...}

在这种情况下,我永远不必按Ctrl + D.我在输入中输入,按Enter键,stdin缓冲区被刷新,并自动检测到EOF。 getword()函数也依赖于它的基础上的getchar(),为什么它会挂起我的程序呢?

从main()调用getword()函数:

while (getword(word, MAX_WORD) != EOF) {
    if (isalpha(word[0])) {
        root = addtree(root, word);
    }
}

getword()函数本身:

int getword(char *word, int lim) {

    char *w = word;
    int c;

    while (isspace(c = getch())) {
    }
    if (c != EOF) {
        *w++ = c;
    }
    // This point is reached
    if (!isalpha(c)) {
        // This point is never reached before Ctrl+D
        *w = '\0';
        return c;
    }
    for ( ; --lim > 0; w++) {
        if (!isalnum(*w = getch())) {
            ungetch(*w);
            break;
        }
    }
    *w = '\0';
    return word[0];
}

我发表评论以表明我确定没有阅读EOF的地方。

getch()和ungetch()函数与第4章波兰表示法计算器中使用的函数相同(该程序能够自动读取EOF - 按Enter键):

#define BUF_SIZE 100

char buf[BUF_SIZE];
int bufp = 0;

int getch(void) {

    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) {

    if (bufp >= BUF_SIZE) {
        printf("ungetch: too many characters\n");
    }
    else {
        buf[bufp++] = c;
    }
}

到目前为止,这是我自本书开头以来编写的第一个程序,它要求我通过Ctrl + D手动输入EOF。我似乎无法弄明白为什么。

提前获得解释......

3 个答案:

答案 0 :(得分:3)

必须键入Ctrl + D才能获得EOF,这是类Unix系统的正常行为。

对于您的代码段:

while ((c = getchar()) != EOF) {...}

输入肯定不应该终止循环(除非你的tty设置严重搞乱)。

尝试编译并运行此程序:

#include <stdio.h>
int main( void )
{
    int c;
    while ((c = getchar()) != EOF) {
        putchar(c);
    }
    return 0;
}

它应该打印您键入的所有内容,并且只有在行开头键入control-D(或者使用control-C将其终止时)才会终止。

答案 1 :(得分:2)

如果您在输入中键入了标点符号,或者您阅读了EOF,则只会达到“未到达”点。如果您键入一个字母或空格,则会被旁路。

当输入来自终端(标准输入)时,在您输入 Control-D (或stty -a输出中指定的任何内容)后才会检测到EOF换行符,或者在你点击另一个 Control-D 之后(所以连续两次)。代码通过换行符读取,因为换行符'\n'满足isspace()

答案 2 :(得分:0)

与我以前的程序混淆的原因是我以前的程序的效果总是打印到stdout 里面 while循环,所以我总是立即看到结果而不需要喂EOF。对于这个,直到while循环结束后才打印树,因此需要EOF遭遇。我没有意识到这一点,这就是我疯狂的原因。

再次感谢你让我直截了当!