我刚刚开始阅读 K&R 书。它介绍了一个 getchar() putchar() 循环程序,用于将字符从输入复制到输出,直到到达 EOF。
main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
我尝试将其改为无限循环,看看当我尝试打印 EOF 时会发生什么。以下是代码:
#include <stdio.h>
int main() {
int c;
while(1) {
c = getchar();
if (c == EOF) {
printf("%d", c); // Since you cannot really use putchar() for EOF as it is -1
// break;
} else {
putchar(c);
}
}
putchar('\n');
return 0;
}
示例输出:
./a.out
a
a
-1
-1
df
df
-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1
我本来希望它打印 -1 然后等待下一个输入,但我发现它只是一直打印 -1。
如果我在打印 EOF 一次后添加一行来中断循环,它会打印 -1 一次然后退出程序,这是可以理解的。
但我不明白为什么没有 break 语句它只是继续循环并打印 -1。
起初我以为它以某种方式使用输出 -1 作为下一个循环的输入(实际上是接下来的 2 个循环,因为 -1 是 2 个独立的字符“-”和“1”),但如果是这种情况,为什么当我放入任何其他字符(如“a”)时没有看到这种无限循环行为,根据我之前的逻辑,这应该连续打印“a”。
有人能帮忙解释一下发生了什么事吗?
根据ISO C23 标准 §7.23.1 ¶6,该函数
getchar
是“字节输入函数”。§7.23.3 ¶11阐述了有关字节输入函数的行为:
§7.23.7.1 ¶3对函数作出如下规定
fgetc
:这意味着一旦设置了文件结束指示符,所有对字节输入函数的进一步调用都将立即失败,而不会尝试读取更多数据。但是,可以使用函数清除文件结束指示符
clearerr
。执行此操作后,根据平台的不同,对字节输入函数的下一次调用可能会成功。您可以使用 清除流的 EOF 和错误状态
clearerr
。getchar()
相当于getc(stdin)
,所以当输入是控制台时,标准输入。现在,一个合乎逻辑的错误行为是记住已到达文件末尾,并返回 EOF 而不执行物理操作
getc
。因此,不会再从 stdin 读取数据。还请注意,您可以从文件重定向,而不是从控制台重定向< ...
。@ikegami 已经提到
clearerr
要清除文件结束状态。(我忘了。)读取磁盘文件无需等待,这只会发生在返回异步生成的数据的设备上,例如终端和网络连接。
此外,结构
stdio
中还有标志FILE
,用于指示是否发生了错误或是否已到达 EOF。一旦设置了其中一个标志,从流中读取总是会立即返回。您可以使用clearerr()
函数清除这些标志,但如果不使用,getchar()
则将继续返回EOF
,即使已将更多数据写入文件。