我正在使用EOF跳出“ while”循环,并希望通过“ scanf”输入一些数字。循环外的“ scanf”不适用于macOS。
我试图在macos和centos上运行此代码。结果是我需要的。
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
//ctrl+d=EOF
while(scanf("%d",&i) != EOF){
printf("?");
}
printf("\nloopend\n");
//those 'scanf' are ignored on macos.
scanf("%d",&i);
scanf(" %d",&i);
scanf("%d ",&i);
printf("\nend\n");
}
输入(不带','): 1,\ n,ctrl + d
输出(centos):
1
?
loopend
//waiting for input here
输出(macos):
1
?
loopend
end
//the program ended directly
答案 0 :(得分:4)
MacOS行为正确。根据{{3}}(fgetc
库函数),文件结束指示是粘性的; fgetc
一旦看到EOF,就必须设置文件的文件结束指示符,这将导致后续调用返回EOF
,直到清除文件结束指示符为止,例如使用{{1 }}:
如果设置了流的文件结束指示符,或者流在文件末尾,则设置了流的文件结束指示符,并且fgetc函数返回EOF。否则,fgetc函数从流指向的输入流中返回下一个字符。如果发生读取错误,将设置流的错误指示符,并且fgetc函数将返回EOF。
由于其他输入功能(包括clearerr()
的作用似乎是通过重复调用scanf
来实现的,因此EOF也应该对它们具有粘性。如果您希望在收到EOF返回单后继续阅读,则应在流中调用fgetc
。 (或其他重置指标的内容,例如clearerr()
。)
多年来,标准C库的Gnu实现未遵循该标准。它仅报告一次EOF,而使下一个seek()
停留在终端和管道等设备上等待更多输入。该错误报告于2006年,是C standard §7.21.7.1/3,于2018年8月发布,尽管该错误可能尚未成为Centos发行版的一部分。
[注意:finally fixed in v2.28中对此行为的讨论时间更长,包括(我本人)现在已经过时的脾气,以及一些有关该问题的历史性讨论的链接。] < / p>
无论如何,由于BSD派生的标准库实现(包括MacOS)遵循上面引用的标准,因此始终清楚可移植代码应调用fgetc
。