15

我最近遇到了一个由使用 fstream::eof() 引起的问题。我从这里读到以下行:

如果已到达相关输入文件的末尾,则函数 eof() 返回 true,否则返回 false。

并且(错误地)假设这意味着如果我使用 fstream::read() 并读取文件末尾,函数 eof() 会告诉我。所以我做了这样的事情(非常笼统):

for(int i = 0; i < max && !file.eof(); i++)
{
     file.read(mything, sizeof(mything));
}

问题的出现是因为稍后在上面链接的页面上解释的内容(由于第一段的误导,我最初没有阅读):

相反,如果在最后一个标记之后碰巧有任何空格,则流不会进入 EOF 状态,但尝试读取另一个标记仍然会失败。因此,EOF 标志不能用作循环中的测试,该循环旨在读取所有流内容,直到 EOF。相反,应该在尝试读取后检查失败情况。

所以我改变了,现在我的循环检查 file.fail() 而不是 file.eof(),我了解 eof() 是如何工作的。我的问题是,为什么它会这样工作?是否存在需要这样做的情况?在我看来,一旦你通过了 EOF,你就通过了 EOF,并且 eof() 应该返回 true。

更新 感谢您的回复,我想我明白了。我正在执行的唯一操作是read(),我立即检查fail(),所以我认为我没问题。现在,我的问题是,我使用 eof() 做什么?

4

2 回答 2

17

因为这样它可以EOF在不知道文件有多大的情况下进行检测。它所要做的只是尝试读取,如果读取很短(但不是错误),那么您已经到达文件的末尾。

这反映了read系统调用的功能,文件 IO 通常最终会调用它(win32 的东西可能会调用ReadFile,但我相信功能是相似的)。

read手册页“返回值”部分(强调添加):

成功时,返回读取的字节数(零表示文件结束),并且文件位置提前该数字。如果此数字小于请求的字节数,则不是错误;这可能会发生,例如因为现在实际可用的字节数较少(可能是因为我们接近文件结尾,或者因为我们正在从管道或终端读取),或者因为 read() 被中断信号。出错时,返回 -1,并适当设置 errno。在这种情况下,未指定文件位置(如果有)是否更改。

顺便说一句:写你想要的东西的好方法是这样的:

T something;
while(file.read(something, sizeof(something))) {
    // process your 'something'
}

这是因为file.read(像 iostream 的许多成员一样)返回对 iostream 本身的引用。所有这些都有一个重载的运算符以允许测试流状态。与 read from 类似std::cinwhile(std::cin >> x) { ... }也可以。

编辑:您应该知道,出于同样的原因,测试与失败可能同样是错误的。如果先前的操作失败,则从您链接到的页面fail()返回。这意味着您需要在测试之前执行读取或其他相关操作。

于 2009-06-24T17:15:21.300 回答
0
int n;
std::cin >> n >> std::stripws;

解决了这个问题。此时您可以使用 .good() 或 .eof()。我喜欢使用 .good(),因为如果有坏磁盘块,.good() 会检测到它。但这就是我。.eof() 不会,您还必须添加 .fail() || 。坏的()。

在对吃空白的问题进行了一番艰苦的研究后,我才发现了这一点。我打算向 iostream 和 ifstream 提出一个 ECO,你瞧,它已经完成了。:-D

于 2012-04-29T11:53:46.357 回答