我最近遇到了使用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()是什么?
答案 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