I have the following code:
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
stringstream buffer("1234567890 ");
cout << "pos-before: " << buffer.tellg() << endl;
buffer.ignore(10, ' ');
cout << "pos-after: " << buffer.tellg() << endl;
cout << "eof: " << buffer.eof() << endl;
}
And it produces this output:
pos-before: 0
pos-after: 11
eof: 0
I would expect pos-after
to be 10
and not 11
. According to the specification, the ignore method should stop when any one of the following condition is set:
- count characters were extracted. This test is disabled in the special case when count equals
std::numeric_limits<std::streamsize>::max()
- end of file conditions occurs in the input sequence, in which case the function calls setstate(eofbit)
- the next available character c in the input sequence is delim, as determined by
Traits::eq_int_type(Traits::to_int_type(c), delim)
. The delimiter character is extracted and discarded. This test is disabled if delim isTraits::eof()
In this case I expect rule 1 to trigger before all the other rules and to stop when the stream position is 10.
Execution shows that it is not the case. What did I misunderstood ?
I also tried a variation of the code where I ignore only 9 characters. In this case the output is the expected one:
pos-before: 0
pos-after: 9
eof: 0
So it looks like in the case where ignore()
extracted the count of characters, it still checks if the next character is the delimiter
and if it is, it extracts it too.
I can reproduce with g++
and clang++
.
I also tried this variation of the code:
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
cout << "--- 10x get\n";
stringstream buffer("1234567890");
cout << "pos-before: " << buffer.tellg() << '\n';
for(int i=0; i<10; ++i)
buffer.get();
cout << "pos-after: " << buffer.tellg() << '\n';
cout << "eof: " << buffer.eof() << '\n';
cout << "--- ignore(10)\n";
stringstream buffer2("1234567890");
cout << "pos-before: " << buffer2.tellg() << '\n';
buffer2.ignore(10);
cout << "pos-after: " << buffer2.tellg() << '\n';
cout << "eof: " << buffer2.eof() << '\n';
}
And the result is:
--- 10x get
pos-before: 0
pos-after: 10
eof: 0
--- ignore(10)
pos-before: 0
pos-after: -1
eof: 1
We see that using ignore()
produces an end-of-file condition on the file. Indicating that ignore()
did try to extract a character after having extracted 10 characters. But in this case, the 3rd condition is disabled and ignore()
should not have tried to look at what the next character was.