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

Jef*_*ger 15 c++ iostream library-design

我最近遇到了使用fstream :: eof()引起的问题.我从这里读到以下内容:

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

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

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

出现这个问题的原因是上面链接的页面稍后解释了(由于误导性的第一段,我最初没有阅读):

相反,如果在最后一个令牌之后恰好有任何空格,则流不会进入EOF状态,但尝试读取另一个令牌仍然会失败.因此,EOF标志不能用作用于在EOF之前读取所有流内容的循环中的测试.相反,应该在尝试阅读后检查失败条件.

所以我改变了,现在我的循环检查file.fail()而不是file.eof(),我理解如何工作eof().我的问题是,为什么这样做?有没有这种情况需要?在我看来,一旦你通过EOF,你已经通过了EOF而eof()应该返回true.

更新 感谢您的回复,我想我已经得到了.我正在执行的唯一操作是read(),我立即检查fail(),所以我觉得我没事.现在,我的问题是,我使用eof()?

Eva*_*ran 16

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

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

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

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

BTW:写一个你想要的东西的好方法是这样的:

T something;
while(file.read(something, sizeof(something))) {
    // process your 'something'
}
Run Code Online (Sandbox Code Playgroud)

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

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