从文本文件读取,直到EOF重复最后一行

时间:2020-03-05 18:41:52  来源:igfitidea点击:

以下C ++代码使用ifstream对象从文本文件(每行有一个数字)读取整数,直到达到EOF。为什么它在最后一行读取两次整数?如何解决这个问题?

代码:

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream iFile("input.txt");    // input.txt has integers, one per line

    while (!iFile.eof())
    {
        int x;
        iFile >> x;
        cerr << x << endl;
    }

    return 0;
}

input.txt:

10  
20  
30

输出:

10  
20  
30  
30

注意:我已跳过所有错误检查代码,以使代码段较小。在Windows(Visual C ++),cygwin(gcc)和Linux(gcc)上可以看到上述行为。

解决方案

回答

只需密切关注事件链即可。

  • 抢10
  • 抢20
  • 抢30
  • 抢EOF

查看倒数第二次迭代。我们抢了30个,然后继续检查EOF。我们尚未到达EOF,因为尚未读取EOF标记(从"二进制"的角度来说,其概念位置在30行之后)。因此,我们继续进行下一个迭代。 x仍然是前一次迭代的30。现在,我们从流中读取并获得EOF。 x仍然为30,并且ios :: eofbit被引发。我们输出到stderr x(这是30,就像在上一次迭代中一样)。接下来,我们要在循环条件下检查EOF,而这次我们不在循环中。

试试这个:

while (true) {
    int x;
    iFile >> x;
    if( iFile.eof() ) break;
    cerr << x << endl;
}

顺便说一句,代码中还有另一个错误。我们是否曾经尝试在一个空文件上运行它?我们得到的行为是完全相同的原因。

回答

我喜欢这个示例,目前,该示例省去了可以在while块中添加的检查:

ifstream iFile("input.txt");        // input.txt has integers, one per line
int x;

while (iFile >> x) 
{
    cerr << x << endl;
}

不确定它有多安全...

回答

有另一种方法可以解决此问题:

#include <iterator>
#include <algorithm>

// ...

    copy(istream_iterator<int>(iFile), istream_iterator<int>(),
         ostream_iterator<int>(cerr, "\n"));