The question comes from https://en.cppreference.com/w/cpp/io/basic_istream/putback, the example code.
#include <sstream>
#include <iostream>
int main()
{
std::istringstream s2("Hello, world"); // input-only stream
s2.get();
if (s2.putback('Y')) // cannot modify input-only buffer
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
s2.clear();
if (s2.putback('H')) // non-modifying putback
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
}
Why s2.putback('Y')
fails but s2.putback('H')
succeed? Isn't the latter also an operation to modify the input-only stream buffer?
Also, I find something confusing while doing some experiments. I add 1 line code compared to the sample above and the second results fails.. Why is it?
#include <sstream>
#include <iostream>
int main()
{
std::istringstream s2("Hello, world"); // input-only stream
s2.get();
if (s2.putback('Y')) // cannot modify input-only buffer
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
std::cout << s2.rdbuf() << '\n'; //1 line code added
s2.clear();
if (s2.putback('H')) // non-modifying putback
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
}
Why
s2.putback('Y')
fails buts2.putback('H')
succeed? Isn't the latter also an operation to modify the input-only stream buffer?
The invocation s2.putback('H')
potentially modifies the buffer, but in this case, it does not, because the data already start with an 'H'
.
You can exemplify the behavior like this:
s2.clear();
assert(s2.putback('H')); // Ok, replacing 'H' with 'H' doesn't change anything
assert(!s2.putback('Z')); // Can't modify.
You can read further the behavior of sputbackc
.
If a putback position is available in the get area (
gptr() > eback()
), and the character c is equal to the character one position to the left ofgptr()
(as determined byTraits::eq(c, gptr()[-1])
, then simply decrements the next pointer (gptr()
).
So in the case of s2.putback('H')
, only the next pointer is decremented. The buffer is not changed.
Answer to your edit: basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb);
extracts the characters maintained by sb
, so after std::cout << s2.rdbuf() << '\n';
the next pointer points to the end of the buffer, which causes s2.putback('H')
to fail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With