【问题标题】:Why does std::fstream set the EOF bit the way it does?为什么 std::fstream 以它的方式设置 EOF 位?
【发布时间】:2010-11-05 14:18:30
【问题描述】:

我最近遇到了一个由使用 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() 用于什么?

【问题讨论】:

  • for(int i = 0; i

标签: c++ iostream library-design


【解决方案1】:

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

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

来自read 手册页“返回值”部分(已添加重点):

成功时,读取的字节数 返回(零表示结束 file),文件位置为 由这个数字推进。它不是一个 如果这个数字小于错误 请求的字节数;这 可能会发生,例如,因为更少 字节现在实际上可用 (也许是因为我们接近 文件结尾,或者因为我们正在阅读 从管道或终端),或 因为 read() 被一个 信号。出错时,返回 -1,并且 errno 设置得当。在这个 情况下未指定是否 文件位置(如果有)发生变化。

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

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

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

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

【讨论】:

  • 我尝试了建议的 while 循环,但注意到当读取的字节数少于 something 的大小时,不会执行循环体。
  • @ChristianAmmer 正确,此代码将处理 整个 对象。如果您想处理字符串行或类似内容,我建议您使用稍微不同但非常相似的循环:godbolt.org/z/Y3dMev
【解决方案2】:
int n;
std::cin >> n >> std::stripws;

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

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

【讨论】:

    猜你喜欢
    • 2017-03-11
    • 2014-06-20
    • 2011-02-03
    • 2021-12-22
    • 2020-08-04
    • 2013-01-13
    • 1970-01-01
    • 2018-11-12
    • 2022-01-15
    相关资源
    最近更新 更多