如何通过仅输入一个 EOF 来结束 scanf

How to end scanf by entering only one EOF

提问人:Tomas Chalupnik 提问时间:11/10/2013 更新时间:11/17/2013 访问量:2295

问:

我正在解决这个问题。我正在使用 while 循环来扫描数字字符串,需要结束扫描并开始继续我的程序的其余部分。我只是想不通,如何刷新 stdin 或做任何事情来不按 Ctrl+D 两次。我只需要发送一次 EOF 来告诉我的循环结束。

while (! feof (stdin))
    {status=scanf ("%d", &array[i]);
    if ( (status != 1 && status != EOF) )
    {       printf("\nWrong input.\n");
            return 1;}
    i++;}
c stdin scanf eof feof

评论

0赞 wildplasser 11/10/2013
将 BY 替换为 。(feof() 总是错的......另外:EOF不是一个字符;您不能像将角色发送到流或文件一样发送它。while (! feof (stdin))while (1)
0赞 mah 11/10/2013
如果是您的终端,则没有 EOF 条件。当文件不是具有有限数据的真实文件,而是可以随时生成更多数据的键盘(真实或虚拟)时,很难到达文件的末尾。stdin
0赞 Tomas Chalupnik 11/10/2013
我替换了它并添加了它,结果是我现在必须按 Ctrl+D 三次while(1)if (status==EOF) break;
5赞 Erik B 11/10/2013
我这辈子从未见过如此奇怪的代码格式。你从哪里学来的?

答:

4赞 AProgrammer 11/10/2013 #1

编辑:这是 glibc 上的错误 1190,它显然是为了 System V 兼容性而故意完成的(Solaris 的行为方式相同,FreeBSD 和 NetBSD 的行为符合预期)。

请注意,您的期望只是部分正确。

CTRL-D 键不是 Unix 中的 EOF 标记。它刷新输入缓冲区,以便程序可以读取它。在 Unix 下被视为 EOF 的是不返回字符的读取,因此如果您刷新一行开头的输入缓冲区,则将其视为 EOF。如果在输入一些尚未刷新的数据后刷新它(自动刷新输入行尾),则需要刷新两次才能读取,该读取不返回任何字符,并将被视为 EOF。

现在,如果我执行这个程序:

#include <stdio.h>

int main()
{
    int status;
    char tab[200];
    while ((status = fscanf(stdin, "%s", tab)) == 1) { 
        printf("Read %s\n", tab); 
        printf("status=%d\n", status);
        printf("ferror=%d\n", ferror(stdin));
        printf("feof=%d\n", feof(stdin));
    }
    printf("\nOut of loop\nstatus=%d\n", status);
    printf("ferror=%d\n", ferror(stdin));
    printf("feof=%d\n", feof(stdin));
    return 0;
}

并且我在一行的开头按 CTRL-D,我得到了我期望的行为:

foo
Read foo
status=1
ferror=0
feof=0
^D
Out of loop
status=-1
ferror=0
feof=1

如果我没有完成这一行,但在 foo 之后按了两次 CTRL-D(如上所述,我希望按两次),我必须按另一个 CTRL-D:

./a.out
foo^D^DRead foo
status=1
ferror=0
feof=1
^D
Out of loop
status=-1
ferror=0
feof=1

我认为这是一个错误,如果输入 while 为 1,则应该立即退出并显示 EOF 结果。scanffeof