问题描述
- c++ peek()和tellg()一起使用的bug
-
cout<<"1-"<<Receive.tellg()<<endl;cout<<"2-"<<char(Receive.peek())<<endl;
cout<<"3-"<<Receive.tellg()<<endl;
cout<<"4-"<<char(Receive.peek())<<endl;
cout<<"5-"<<Receive.tellg()<<endl;
cout<<"6-"<<char(Receive.peek())<<endl;
cout<<"7-"<<Receive.tellg()<<endl<<endl;
程序的其他部分与问题无关,大概是从尾到头读一个txt文件里的所有字符,我在debug的时候发现了这个现象:
1. 第一个tellg返回的指针位置是正确的,但是如果后面跟着一个peek,再用tellg返回指针位置就会+1了。peek按理来说不会移动文件指针,但后面再重复几次又不会每次都+1。
2. 貌似是跟windows系统换行符有关,如果txt文件里没有换行符的话就没有这个问题。我google了一下,发现国外很多论坛有人提相同的问题,有人解答说peek+tellg是c++的一个经典bug,不过也没有找到清楚的解答,求大神指点!
解决方案
std::istream::peek
int peek();
Peek next character
Returns the next character in the input sequence, without extracting it: The character is left as the next character to be extracted from the stream.
返回下一个,但是不提取,所以还是保留在原来的位置。
解决方案二:
"http://compgroups.net/comp.lang.c++.moderated/peek-and-tellg/39837"也许可以帮助到你。
"it mixes two different ways of accessing a stream:
-- as a one-pass input stream with limited pushback
-- as a random-access sequence with bookmarks
It has been known for decades that trying to access the same stream both ways is fraught with peril. Whether you call the resulting surprising behavior buggy or regrettable is a matter of taste.
If you want robust code, don't mix peek and seek/tell."
没看太懂啥意思,只知道peek和seek/tell混用会有问题。
std::istream::peek
Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to true). Then (if good), it reads one character from its associated stream buffer object by calling its member function sgetc, and finally destroys the sentry object before returning.
std::istream::tellg
Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to true) without evaluating it. Then, if member fail returns true, the function returns -1.
Otherwise, returns rdbuf()->pubseekoff(0,cur,in). Finally, it destroys the sentry object before returning.