2

考虑下面的 C++ 程序,它接受一个文件并打印每一行。它是一个更大程序的一部分,我稍后会根据我看到的内容将其附加到文件中。

#include <fstream>
using std::fstream;
#include <iostream>
#include <string>
using std::string;

int main()
{
 fstream file("file.txt", fstream::in | fstream::out | fstream::app);

 string line;
 while (std::getline(file, line))
  std::cerr << line << std::endl;

 return 0;
}

现在应用这个版本的file.txt(第一行一个单词,后跟一个换行符):

Rain

在我的机器(Snow Leopard)上,这没有打印出来。仔细检查,第一次调用 getline 失败。奇怪的是,如果我添加第二行,它也会失败:仍然没有打印!

谁能解开这个谜?

4

2 回答 2

9

当你说:

fstream file("file.txt", fstream::in | fstream::out | fstream::app);

您以附加模式打开文件 - 即在最后。只需在阅读模式下打开它:

fstream file("file.txt", fstream::in );

或使用 ifstream:

ifstream file("file.txt" );

当然,正如 Earwicker 建议的那样,您应该始终测试打开是否成功。

如果确定要以追加模式打开,则可以显式移动读取指针:

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

int main() {
    fstream file( "afile.txt", ios::in | ios::out | ios::app );
    if ( ! file.is_open()  ) {
        cerr << "open failed" << endl;
        return 1;
    }
    else {
        file.seekg( 0, ios::beg );   // move read pointer
        string line;
        while( getline( file, line ) ) {
            cout << line << endl;
        }
    }
}

编辑:似乎在打开文件时使用的标志组合会导致特定于实现的行为。上面的代码适用于 Windows 上的 g++,但不适用于 Linux 上的 g++。

于 2010-02-21T10:00:16.317 回答
2

您应该检查文件是否已实际打开:

if (!file)
    std::cerr << "Oh dear" << std::endl;

更新:实际上文件可能已打开,但处于附加模式 - 请参阅 Neii 的答案。

更新2:好的,又错了。至少在 Leopard 的 g++ 中,文件不会被打开,因为app标志与标志不兼容in。所以上面的检查会打印出来Oh dear

在 MSVC++ 中,它继续打开文件,显然在开始时读取位置,这解释了为什么其他人看到它工作,我为怀疑他们的真实性道歉!

于 2010-02-21T09:48:54.810 回答