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

C K&;R:第6章-为什么getword()函数不读取EOF?,c,eof,C,Eof,这是我关于堆栈溢出的第一篇文章,所以我希望我不要踩到任何人的脚 当然,所有的输入都是受欢迎和赞赏的,但那些最适合回答问题的人实际上已经读过《C编程语言》第二版 我刚刚完成了编码练习6-4,但我似乎想不出什么。为什么getword()函数在我按下Ctrl+D(在ArchLinuxVM中我用C编写代码)之前不读取EOF 这本书中我以前的许多练习都需要阅读stdin。一种方法是通过类似 while ((c = getchar()) != EOF) {...} 在这种情况下,我永远不必按Ctrl+D。

这是我关于堆栈溢出的第一篇文章,所以我希望我不要踩到任何人的脚

当然,所有的输入都是受欢迎和赞赏的,但那些最适合回答问题的人实际上已经读过《C编程语言》第二版

我刚刚完成了编码练习6-4,但我似乎想不出什么。为什么getword()函数在我按下Ctrl+D(在ArchLinuxVM中我用C编写代码)之前不读取EOF

这本书中我以前的许多练习都需要阅读stdin。一种方法是通过类似

while ((c = getchar()) != EOF) {...}
在这种情况下,我永远不必按Ctrl+D。我在输入中输入,然后按enter,stdin缓冲区被刷新,EOF被自动检测。getword()函数的基函数也依赖于getchar(),那么为什么它会挂起我的程序呢

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

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章中波兰符号计算器中使用的函数相同(该程序能够通过按Enter键自动读取EOF):

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


事先非常感谢您的解释……

只有在输入中键入标点符号或阅读EOF时,才能达到“未达到”点。如果键入一个字母或空格,则会将其忽略


当输入来自终端(标准输入)时,在输入换行符后或在点击另一个Control-D(一行两个)后键入Control-D(或
stty-a
output中指定的任何内容)之前,不会检测到EOF。代码读取换行符是因为换行符
'\n'
满足
isspace()

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

对于您的代码片段:

while ((c = getchar()) != EOF) {...}
按Enter键肯定不会终止循环(除非tty设置严重混乱)

请尝试编译并运行此程序:

#include <stdio.h>
int main( void )
{
    int c;
    while ((c = getchar()) != EOF) {
        putchar(c);
    }
    return 0;
}
#包括
内部主(空)
{
INTC;
而((c=getchar())!=EOF){
普查尔(c);
}
返回0;
}

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

与我以前的程序相比,我的困惑的根源是我以前的程序的效果总是打印到while循环中的stdout,所以我总是在不需要输入EOF的情况下立即看到结果。对于这一个,树直到while循环结束后才会打印,因此需要EOF遭遇。我没有意识到这一点,这就是为什么我会发疯的原因


再次感谢你让我明白过来

要格式化代码,请突出显示它,然后单击
{}
图标。这将突出显示的区域缩进4个空格,这就是“标记”表示源代码的方式。另见。我已经为你修好了。欢迎来到Stackoverflow!或者在一行中键入两个control-D。或者当你用“退出”信号杀死它时:谢谢你的回复。我重新检查了我的代码,你是对的。当我按Enter键时,sdtin缓冲区会被刷新到屏幕上,但在我按Ctrl-D或Ctrl-C键之前,不会遇到EOF。我不知何故将EOF与“\n”混淆了。您也是对的,先生,输入一个非字母表将达到我指出的点,这在Control-D之前是永远不会达到的。我只是在单词树的上下文中思考单词。
while ((c = getchar()) != EOF) {...}
#include <stdio.h>
int main( void )
{
    int c;
    while ((c = getchar()) != EOF) {
        putchar(c);
    }
    return 0;
}