【问题标题】:ifstream.eof() not evaluating to true in C++ [duplicate]ifstream.eof() 在 C++ 中未评估为真 [重复]
【发布时间】:2014-12-03 15:30:01
【问题描述】:

我在理解 C++ 中的文件输入流方面有点吃力。我有一个代码 sn-p 如下:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
    ifstream in("x.txt");

    bool done = false;
    do {
        string input = "";
        getline(in,input);
        int x1;
        int x2;
        in >> x1;
        in >> x2;
        cout << input << " " << x1 << " " << x2 << endl;
        in.ignore();
        if(in.eof()) {
            done = true;
            cout << "reached eof" << endl;  
        }
    } while(!done);

    return 0;
}

x.txt 文件如下所示

task1
12
1313
task2
13
1414
[blank line]

请注意在输入文件末尾有意包含的空白行。这意味着在输入“1414”后按下了回车键。

我的预期输出是

task1 12 1313
task2 13 1414
reached eof

但实际上,输出是

task1 12 1313
task2 13 1414
 13 1414
reached eof

我知道在输入文件中按 Enter 会生成一个隐式换行符,在使用像 getline(ifstream, string) 这样的语句之前,我们应该 ignore() 下一个换行符。话虽如此,为什么即使我 ignore() '1414' 之后的隐式换行符, ifstream.eof() 也不评估为真?

【问题讨论】:

  • while(in &gt;&gt; x1 &gt;&gt; x2)
  • 你为什么不测试getline的返回值? in &gt;&gt; x1in &gt;&gt; x2 有同样的问题吗?如果您遇到 I/O 问题检查 I/O 是否工作
  • 这基本上是 stackoverflow.com/q/5605125/981959 的副本,但循环不同(但仍然是错误的)

标签: c++ file input ifstream eof


【解决方案1】:

eof 标志只有在您尝试读取文件末尾之后才会设置。相反,您应该在从流中读取后检查结果,可能类似于

while (getline(in, input) && in >> x1 >> x2) {
    cout << input << " " << x1 << " " << x2 << endl;
    in.ignore();
}
cout << "reached eof" << endl;  

【讨论】:

  • 他可能也应该忽略直到'\n',以防万一行尾有多余的空白。
【解决方案2】:

在第二个循环结束时,流位置在末尾,但在您尝试读取更多数据之前不会设置eofbit。让我们考虑一下在前两个循环运行并第三次进入循环之后会发生什么:

你尝试读一行:

    getline(in,input);

这没有读取任何内容,因为您已经到达了流的末尾,所以它设置了eofbit,并且因为没有提取任何内容也设置了failbit。但是你不检查是否读取了一行,或者input是否为非空,你只是盲目地继续

你声明了两个未初始化的变量:

    int x1;
    int x2;

然后尝试再次阅读:

    in >> x1;
    in >> x2;

这甚至不会尝试读取任何内容,因为 failbit 已设置,但您也无需在此处检查它。 x1x2 保持不变且未初始化。

然后你打印出未初始化的整数,这恰好打印出 previous 循环中的值,因为这恰好是在堆栈上:

    cout << input << " " << x1 << " " << x2 << endl;

这没有任何作用,因为设置了failbit

    in.ignore();

现在终于你检查了流状态,但是要防止上述所有问题已经太晚了:

    if(in.eof()) {

您应该检查 I/O 操作是否成功,而不是假设他们成功了,然后在很久以后才发现有问题,而采取任何措施都为时已晚。

检查 I/O 操作的方法是在布尔上下文中测试流,例如if (in),您应该检查 EOF,因为直到您到达流的末尾并尝试再次读取 时才会设置它。 p>

迈克的回答显示了正确的方法,但您也应该阅读Why is iostream::eof inside a loop condition considered wrong?

【讨论】:

  • 如果他已经提取了文件的最后一个字符(带有ignore),那么eofbitfailbit应该设置在getline中,在in &gt;&gt; x1之前到达。
  • @JamesKanze,啊,是的,我错误地忽略了忽略 :) 我确实提到过当设置 failbit 时它甚至不会尝试做任何事情,我会更清楚地说明
猜你喜欢
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 2017-04-28
  • 2018-02-24
  • 1970-01-01
相关资源
最近更新 更多