更改文件内容 - 这是g ++ 4.7.2中的错误还是我做错了?

时间:2016-10-06 17:16:15

标签: c++ c++11

在编写一些代码来更新二进制文件中的位置时,我发现了一些奇怪的东西。请考虑以下示例代码:

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

int main() {
    char tmp;
    string s;
    fstream fs;

    fs.open("test.txt", fstream::out);
    fs << "blub" << endl;
    fs.close();
    fs.open("test.txt", fstream::in);
    fs >> s;
    cout << s << endl;
    fs.close();

    fs.open("test.txt", ios::in|ios::out|ios::binary);
    if (!fs.is_open() || !fs.good())
        cerr << "could not open!" << endl;

    fs.read(&tmp, 1);
    fs.read(&tmp, 1);
    //fs.tellg(); //<-- required to fix for old g++?
    const char *c = "ah";
    fs.write(&c[0], 1);
    fs.write(&c[1], 1);
    fs.close();

    fs.open("test.txt", fstream::in);
    fs >> s;
    cout << s << endl;
}

在最近的g ++版本中(至少在6.2.1版本中),我可以只读取然后写一些没有问题的字节 - 在这个例子中你得到了正确的输出:

blub
blah

然后我用g ++ 4.7.2编译代码,突然更新没有效果,即第二个输出仍然是“blub”,除非我添加fs.tellg()或fs.tellp ()。我发现了this的问题,但据我了解,这是Windows的限制,但我在Linux下工作。

现在我想知道,这是旧g ++中的一个错误还是我做错了,并且幸运的是现代g ++版本,它只是有效吗?第二个问题,为什么要求当前的位置解决它?

提前致谢!

1 个答案:

答案 0 :(得分:2)

  

现在我想知道,这是旧g ++中的一个错误

不,在这方面g ++没有错误。

  

或者我做错了

是。您在链接的answer中对此进行了解释。

  
    

...如果没有对fflush函数或文件定位函数(fseek,fsetpos或rewind)的干扰调用,输出不应直接跟随输入,并且输入不应直接跟随输出而不进行干预调用到文件定位功能,除非输入操作遇到文件结尾。

  

哪个来自C标准,但通过以下方式相关:

  
    

读取和编写由basic_filebuf类对象控制的序列的限制与使用标准C库FILE读取和写入的限制相同。

  

有一个错误,但它在您的代码中。您的计划不符合标准规定的要求。

  

但据我了解,这是Windows下的限制

可能是这种情况,但更一般地说,限制是在C ++(和C)规范中。标准库是否具有限制对库是否符合标准没有影响。任何依赖于不存在限制的代码都不符合标准。

  

并且[我]幸运地使用现代g ++版本

有人可能会说你不走运。当程序不起作用而你发现了这个错误时,这是​​一个好运。

  

第二个问题,为什么要求当前的位置解决它?

我怀疑tellg是否足以使您的程序符合标准。所以,我会说它“偶然”修复了这个程序。

您应该使用std::flush(fs);代替。

  

这是否意味着新版本符合LESS标准?

不,这两个版本的g ++在这方面同样兼容。你的计划不是。