2个有趣的问题
ferror()
ferror()
反映了流中错误指示器的状态。此标志在发生罕见的输入错误时被设置,并保持设置直到被清除 - 请参阅 clearerr()
。如果读取输入时发生错误,并且稍后的代码再次读取,而不进行清除,ferror()
仍然报告为真,即使以下读取没有错误。
fgetc()
返回 EOF
可能是由于文件结束(常见情况)或罕见的输入错误。最好使用 feof()
而不是 ferror()
进行区分。 ferror()
可能是由于先前的错误而不是当前的情况 - 当然是因为文件结束。
int c;
c = fgetc(file);
if (c == EOF) {
if (feof(file)) puts("end-of-file");
else puts("input error");
}
宽字符: 因为C语言中有一个边界情况,所以测试错误条件的问题就出现了。
fgetc()
返回一个int
。其值在unsigned char
和EOF
(一些负数)的范围内。
int ch;
while ((ch = fgetc(fp)) != EOF) {
}
if (ferror(fp)) Handle_InputError();
if (feof(fp)) Handle_EndOffFile();
然而,C语言允许unsigned char
拥有比int
正数范围更广的范围。将unsigned char
转换为int
具有实现定义的行为,可能会导致unsigned char
值被转换为负的int
,并且与EOF
匹配。
这样的平台很少见,不在2015年的主流。大多数平台将具有UCHAR_MAX <= INT_MAX
,通常使用上述样式。这些平台很难成为常见的平台,因为像上面那样依赖于EOF
与转换为int
的unsigned char
不同的代码量。
如果代码需要处理UCHAR_MAX > INT_MAX
的罕见情况,则
int c;
for (;;)
{
c = fgetc(file);
if (c == EOF) {
if (feof(file)) break;
if (ferror(file)) break;
}
}
在while ( !feof (file) ) always wrong?中的普遍参考提醒了我们在检查错误之前使用fgetc(in)
结果时,代码通常会犯的错误。其他答案中的两个代码都在使用fgetc()
结果之前检查错误条件。
第二个代码处理了所有情况,包括可能只适用于某些被遗忘的电脑堆积垃圾的计算机。而第一个则更加常见。
while (cin >> c)
,而绝对不是while (!cin.eof())
。请参见为什么在循环条件中使用iostream::eof被认为是错误的。 - Bo Persson