【问题标题】:What does eof() returns?eof() 返回什么?
【发布时间】:2013-04-09 11:52:05
【问题描述】:

代码如下:

string fname = "/home/jack/example.csv";
ifstream csvin(fname.c_str());
if (csvin.eof()) {
    do_something;
}

我的问题是:eof() 在什么情况下返回 true。我有以下选择:

  1. 文件不存在。
  2. 文件为空。
  3. 文件不存在或为空。

不幸的是documentation 没有帮助,因为我不知道eofbit error state flag 的意思。我也不明白End-of-File is reached in the sequence associated with the stream 是什么意思。我假设 c_str() 返回一些迭代器,如果它已经被某些东西使用它可能已经到达终点。但是,我对c_str() 的结果是新鲜的简单情况感兴趣,如果文件不存在它将返回什么,如果文件为空,它将返回什么?

已编辑

我只想知道上面给出的代码在两种情况下返回了什么:

  1. 文件不存在。
  2. 文件为空。

【问题讨论】:

  • 通常是这样写的:while(!csvin.eof()) {do_something();}
  • @Gearoid 否。除非“通常”,否则您的意思是“通常,在损坏的代码中”
  • 您的文档导致您陷入了循环,因为该网站很容易这样做。将此站点视为您的第一个来源。 en.cppreference.com/w/cpp/io/basic_ios/eof
  • 如果文件不存在,csvin 无效,你不应该首先尝试调用eof()...
  • @DevSolar: csvin 将是一个完全构造的对象,因此在其上调用任何方法(包括eof)都是明确定义的(尽管在eof 的情况下无用)。失败的构造函数将设置失败位,这将阻止需要有效流的进一步操作成功。

标签: c++ eof c-str


【解决方案1】:

eof() 当您在正在读取的流中的位置到达文件末尾时返回 true。它实际上返回读取文件末尾(试图读取过去)时设置的 eof 标志 的值。查看 C++: .eof on an empty file 讨论关于 eof 和空文件的讨论!

【讨论】:

  • 如果有一些不赞成投票的理由会很好。
  • 我没有投反对票,但您的回答不正确。当您尝试读取文件末尾过去时,设置了 eof 位。如果您只是读取最后一个字节,则 eof 尚未设置 。这就是为什么这么多 while ( ! eof() ) 构造如此悲惨地失败的原因:他们认为,因为上一次操作成功,下一次操作也会成功......
【解决方案2】:

eof 如果设置了 eofbit 标志,则返回 true(表示在 ifstream 的情况下到达文件末尾)。

当输入操作尝试读取流的末尾(iow:到达流的末尾)时,可以通过流上的所有输入操作(例如read)设置 eofbit 标志。正如评论中所指出的,即使从概念上讲,只要读取最后一个字符(或不读取空流上的任何内容)就到达流的末尾,但流在尝试读取另一个字符之前并不知道这一点.有关详细信息,请参阅每个输入操作的文档。

请注意,构造流不是输入操作,因此在您展示的代码示例中,在到达 if 语句时不会设置 eofbit。 如果由于某种原因构造流失败(例如,文件不存在),则将设置失败位,可以使用fail 进行检查。

编辑:看到您的编辑,我希望能更清楚地说明上述内容:

在您发布的代码中,if 条件永远不会计算为真,因为ifstream 构造函数没有设置 eofbit。

如果文件不存在,将设置故障位,您可以像这样检查:

if (csvin.fail()) {
    // oops : failed to open the file for reading (file doesn't exist, or has the wrong permissions, or ...)
}

在文件为空的情况下,构造函数不会报错,但对流的第一个输入操作会设置 eofbit。在第一次输入操作之后,您可以使用eof 检查是否已到达文件末尾。

【讨论】:

  • 您的第二段不明确。 “到达流的尽头”是什么意思?如果我打开一个空文件,在尝试任何输入之前我已经“到达”了流的末尾。我认为你应该稍微澄清一下。 (当然,关键是流试图查看一个字符,但没有。尽管这也引出了一个问题:流何时尝试查看一个字符。某些输入需要先行,其他没有。)
  • @JamesKanze:公平点,并相应地添加了一些说明。当谈到“到达流的尽头”时,我是从流代码的观点出发的——不是概念上的。两者之间确实存在歧义。
【解决方案3】:

eof() 返回true 如果流上的最后一个操作 试图读取文件的最后一个字节。请注意,它告诉您有关上一次操作成功的信息,而不是下一次操作的成功。许多代码示例都做出了错误的假设,即它会告诉您有关下一个操作的一些信息,因此代码的行为将与预期不符。

【讨论】:

  • 我不同意你的第二句话。但这取决于eof() 返回的内容(以及操作是否成功)。如果eof() 返回true,它确实告诉您下一个操作将失败。如果它返回 false,它告诉你前面的操作没有因为文件结束而失败。 (它可能由于其他原因而失败。)
【解决方案4】:

实际上存在一定程度的实现依赖性,因为 当eofbit 被设置时。 (函数eof() 返回真 当且仅当设置了eofbit。)需要设置 如果,在阅读某些东西的过程中(格式化或 未格式化),调用streambuf::sgetc()(或其中一个 其他字符获取器)返回std::char_traits::eof()。 何时实施可能看起来并不总是很清楚 前面的字符——如果这样做到文件结尾,它 设置eofbit;如果它不做前瞻,它就不会。

我也不确定实现是否可以设置eofbit 如果它知道下一次读取必须返回eof, 没有实际阅读;我相当确定 然而,现有的实现却没有。 (你真的想要 eofbit 在您寻找文件末尾时设置?)所以在您的 例如,您几乎肯定不会看到 eof() 返回 真的。

所有这些都解释了为什么你几乎从不这样做input.eof()(或 input.good(),其值中包含eofbit 好吧)。尝试打开文件后,通常的情况是 if ( input.is_open() ),虽然input.fail() 可以用作 好吧。在读取已经打开的文件时,我们测试 input.fail()尝试输入之后,通常使用 布尔上下文中的流对象(即if ( input ),或if ( !input ))。 检测到故障后,我们可以使用 eof()判断失败的原因是否是结束 文件或其他一些错误(如尝试输入时的"abc" int)。即便如此,它也不是 100% 可靠的,eof() 可能 即使格式有错误,也返回 true。 (考虑:

std::istringstream s( "1.3E+" );
double d;
s >> d;

在这种情况下,s.eof() 几乎肯定会返回 true, 尽管输入失败是因为错误 格式,而 不是 因为文件结尾。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-23
    相关资源
    最近更新 更多