关于c++文件I/O和fstream的问题

a quesition about c++ file I/O and fstream

我需要打开一个文件并获取第一个 character.If 我用 ios::in 打开文件,当文件没有 exist.So 时它不会创建文件无法打开文件,我用 ios::out 打开文件,它会创建一个空文件,所以我可以在文件中输入“0”。

fstream passengerData;
passengerData.open("passenger.txt",ios::in);
if (!passengerData)
{
    passengerData.open("passenger.txt",ios::out);
    passengerData << '0' ; 
    passengerData.close();
}

当我运行 this in visual studio 2015时,它可以在visual c++ 6.0中工作well.But,它只能创建一个空文件,'0'不输入进入file.I 想知道为什么结果不同以及如何解决问题。 我还想知道当我使用 ios::in|ios::outios::in|ios::out|ios::app.

时按位运算符 OR 是如何执行的

fstream::open on cppreference 的文档看来,它似乎只是从 C++11 开始也打开了 clear() 成功标志,所以也许如果你在调用之前手动清除标志 open 调用也会在 VC++6:

中成功
fstream passengerData;
passengerData.open("passenger.txt",ios::in);
if (!passengerData)
{
    passengerData.clear();
    passengerData.open("passenger.txt",ios::out);
    passengerData << '0' ; 
    passengerData.close();
}

此外,您还需要在第二次调用 open 后检查 passengerData 的状态。

MicroVirus 的预感是正确的。我想详细解释一下为什么什么都没发生。

基本上,当 passengerData.open("passenger.txt",ios::in); 设置 failbit 时。现在你确实用 passengerData.open("passenger.txt",ios::out); 重试了,它确实成功了(原文如此!),尽管错误位没有被清除(c++11 之前的行为),并使随后的 operator<< 什么都不做。

我想这是标准中的一个缺陷,vc++6 对于 c++11 来说太旧了。

cppreference 来源解释了行为:

您使用 operator<<, which is a FormattedOutputFunction 表示:

A FormattedOutputFunction is a stream output function that performs the following:

  • Constructs an object of type basic_ostream::sentry with automatic storage duration, which performs the following:

    • if eofbit or badbit are set on the output stream, sets the failbit as well [...]

因此它检查流 (passengerData) 是否可操作。现在,有趣的是,eofbad 位都没有设置,所以这似乎是一个错误的方法,但是下一步:

  • Checks the status of the sentry by calling sentry::operator bool(), which is equivalent to basic_ios::good.

其中包含 eof-fail-bad- 位。那些是 iostates。在 failbit 部分你可以找到:

The failbit is set by the following standard library functions:

  • The constructors of std::basic_fstream, std::basic_ifstream, and std::basic_ofstream that takes a filename argument, if the file cannot be opened.
  • basic_fstream::open, basic_ifstream::open, and basic_ofstream::open if the file cannot be opened.

您可以在第二次打开后检查 iostate 位来确认这一点:

fstream passengerData;
passengerData.open("passenger.txt",ios::in);
if (!passengerData)
{
    passengerData.open("passenger.txt",ios::out);
    if (passengerData.rdstate() & std::ios_base::fail) {
       std::cout << "stream has failbit set\n";
    }
    passengerData << '0' ; 
    passengerData.close();
}