编辑:它是 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
我认为这是一个错误,scanf
如果在为 1 时输入,则应该立即以 EOF 结果退出feof
。