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

时间:2013-11-10 11:43:25

标签: c stdin scanf eof feof

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

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

1 个答案:

答案 0 :(得分:3)

编辑:it's bug 1190 on glibc,显然是为了系统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

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

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

并且我认为这是一个错误,如果在scanf为1时输入,则feof应立即退出并显示EOF结果。