在编写一些代码来更新二进制文件中的位置时,我发现了一些奇怪的东西.考虑这个示例代码:
#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版本,它只是有效吗?第二个问题,为什么要求当前的位置修复它?
提前致谢!
最佳答案
Now I wonder, is this a bug in the old g++
不,在这方面没有错误.
or am I doing it wrong
是.您在链接的answer中对此进行了解释.
… output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end- of-file.
这是来自C标准,但通过以下方式提出相关:
The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf are the same as for reading and writing with the Standard C library FILEs.
有一个错误,但它在您的代码中.您的计划不符合标准规定的要求.
but as I understand, this is a limitation under Windows
可能是这种情况,但更一般地说,限制是在C(和C)规范中.标准库是否具有限制对库是否符合标准没有影响.任何依赖于不存在限制的代码都不符合标准.
and was [I] just lucky with the modern g++ version
有人可能会说你不走运.当程序不起作用而你发现了这个bug时,这是一个好运.
Second question, why does asking for the current position fix it?
我怀疑tellg足以使您的程序符合标准.所以,我会说它偶然“修复”了这个程序.
你可能应该使用std :: flush(fs);代替.
this would mean that the NEW version is LESS standard compliant?
不,这两个版本的g在这方面同样合规.你的程序不是.