0

I'm practicing using C & Unix by writing up some of the C programs in Vim and compiling them.

The word count program is supposed to end when the character read is EOF (CTRL-D). However, when I run it, the first CTRL-D pressed just makes it print "^D" (minus the quotes) on the terminal. The second time it's pressed, the "^D" goes away and it terminates normally.

How can I change this so that it terminates after only one CTRL-D? I notice that if I've just made a newline character, then pressing CTRL-D once does the trick. But I don't really understand why it works then and not in the general case.

Here's what the program looks like for those of you who don't have the book.

enter image description here

#include <stdio.h>

#define IN   1   /* Inside a word */
#define OUT  0   /* Outside a word */

int main()
{
    int c, nl, nw, nc, state;
    state = OUT;
    nl = nw = nc = 0;
    while ((c = getchar()) != EOF) {
        ++nc;
        if (c == '\n') {
            ++nl;
            --nc;
        }
        if (c == ' ' || c == '\n' || c == '\t')
            state = OUT;
        else if (state == OUT) {
            state = IN;
            nw++;
        }
    }
    printf("%d %d %d\n", nl, nw, nc);
    return 0;
}
4

2 回答 2

2

Unix 类型系统中的输入通常取自 shell,最常见的是规范模式,这意味着它部分由 shell 干预,以实现控制命令使用方式的重要控制功能。这种控制功能的一个例子是使用 control-X 来清除当前行。在您的情况下发生的情况是外壳程序(例如 bash)将 control-D 解释为关闭输入流的用户命令。所有先前的字符以及 control-D 都会发送到您的程序,但 control-D 尚未转换为 EOF。当所有字符都已发送完毕时,就像换行之后的情况一样,bash 不会拦截 control-D 函数,而是将 control-D 重新解释为独立输入,并将其转换为指示 EOF。

有关更多信息,请参阅先前的答案:

ctrl-d 没有停止 while(getchar()!=EOF) 循环

于 2013-09-15T05:11:16.570 回答
1

如果您在行首键入Control-D,一次就足够了。如果在键入任何内容后键入 Control-D,则需要键入两次。

这是因为它Control-D告诉终端驱动程序将所有可用字符发送到任何等待进程。当它位于行首时,没有可用的字符,因此等待 a 的进程read()返回零个字符,这就是 EOF(没有可读取的字符)的含义。当它通过一行时,第一个Control-D将字符发送给程序,程序读取它们;第二个表示不再有字符,因此再次表示 EOF。

于 2013-09-15T04:52:39.597 回答