为什么std :: fstream设置EOF位的方式呢?

时间:2009-06-24 17:04:25

标签: c++ iostream library-design

我最近遇到了使用fstream :: eof()导致的问题。我从here中读到以下一行:

  

如果已到达关联输入文件的末尾,则函数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()是什么?

2 个答案:

答案 0 :(得分:16)

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

这反映了read系统调用的功能,哪个文件IO通常最终调用(win32内容可能调用ReadFile但我相信功能类似)。

read联机帮助页“返回值”部分(重点添加):

  

成功时,读取的字节数   返回(零表示结束   文件),文件位置是   由这个数字提前。它不是   如果此数字小于,则出错   请求的字节数;这个   可能会发生,例如因为更少   字节实际上现在可用   (也许是因为我们接近了   文件结束,或者因为我们正在阅读   从管道,或从终端),或   因为read()被a打断了   信号。出错时,返回-1,并且   errno设置得恰当。在这   如果没有指定的话   文件位置(如果有)改变。

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

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

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

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

答案 1 :(得分:0)

int n;
std::cin >> n >> std::stripws;

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

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