eof()是不好的编程习惯吗?

25

你的意思是 feof() 函数吗? - Oliver Charlesworth
2
他可能指的是iostream::eof()这个函数。 - Puppy
4个回答

36
你可以使用eof函数来检测它所报告的确切条件 - 是否尝试读取了超出文件末尾的位置。但你不能使用它来测试是否有更多的输入可供读取,或者是否读取成功,这些是更常见的测试方式。

错误的:

while (!cin.eof()) {
  cin >> foo;
}

正确:

if (!(cin >> foo)) {
  if (cin.eof()) {
    cout << "read failed due to EOF\n";
  } else {
    cout << "read failed due to something other than EOF\n";
  }
}

但是如果你已经读到文件的末尾,难道不应该没有剩余的信息吗? - Sam
4
@Sam:eof()并不意味着“文件位置在结尾,下一次读取将失败”。它的意思是“你试图读取超出文件结尾的内容,而这个操作失败了”。 - Erik
1
@Sam:重点是在 while (!eof()) { cin >> foo; } 循环中,你并不是读取 直到 文件结束。你是读取直到文件结束 再多读一次。而且你没有测试其他可能导致读取失败的方式。 - Erik
7
@Sam: int foo; while (!cin.eof()) { cin >> foo; cout << foo << "\n" }。这是一个典型的结构,它并不能完成程序员预期的功能。它最多只能读取所有整数并将它们显示出来,然后再显示最后一个整数一次。如果你输入 "1 2 abc",它将读取和显示 "1"、"2",然后无限循环地显示 "2"。 - Erik
1
@Portablejim 很不幸,你的教授是错的,那样做完全没有帮助。无论你如何编写循环条件,它都不起作用。有时它会创建额外的轮回,或者会省略最后一个有效值。eof()为false并不能保证下一次读取将成功(第一个谬论)。即使成功读取后,eof()也可能为true(第二个谬论)。 - Tronic
显示剩余3条评论

12

如果输入失败的原因不同,你就会遇到麻烦,所以不应该使用它。

while(!file.eof()) {
    int i;
    file >> i;
    doSomething(i);
}

如果文件的内容是"WHAARRRRRRGARBL",那么在上述循环中会发生什么?它将无限循环,因为它不是文件结尾,但您仍然无法从其中提取一个整数。


只是随口一想,你可不可以把它放在一个字符串中然后进行操作?或者那样效率低下吗? - Sam
低效,使用格式化输入如 cin >> somedouble >> someint >> somechar; 有什么意义呢? - Drise

4

你是如何使用它的? .eof() 会告诉你流已经到达了文件末尾,试图读取不存在的数据。

通常情况下,这不是你想要的。通常,你想知道是否正在接近文件末尾,而不是已经到达了文件末尾。在像这样的循环中:

while(!f.eof())
{
    f >> /* something */;
    /* do stuff */
}

你将尝试读取输入并失败,然后执行 /* do stuff */ 中的所有内容,然后循环条件失败并停止循环。该循环的另一个问题是,输入可能会以其他方式失败。如果文件存在错误条件但不是 EOF,则 .fail() 将返回 true,但 .eof() 不会。

那么你的意思是因为我选择用的变量或数据容器不适合这种类型,是吗?我不确定为什么这对我来说显得如此令人困惑。 - Sam
@Sam:读取错误的数据是可能的,但你需要单独处理。它不会触发.eof()函数或任何其他类似的函数。然而,如果在读取文件时出现系统错误,您可能也希望停止。 - David Thornley

3
如果以上回答让您感到困惑:
人们认为eof()的作用是错误的:
- eof()不会检查您读取的最后一部分是否包含文件的最后一个字节。 - 它不会检查下一个字节是否在文件结束之后。
它实际的作用是:
- eof()报告最后一次读取是否包含了文件结尾后的字节。
如果eof()为true,那么您已经犯了一个错误。这解释了教授的陈述。只需将其用作其意义所在,表示发生了错误即可。

读取文件末尾之后的内容并不是错误,而是一种非常正常的操作。例如,考虑istringstream s("123"); int i; s >> i;现在s.eof()为true(因为读取时必须查看是否有第四个数字),s.fail()为false(因为读取成功),i包含值123。 - Tronic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接