Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between modifying and non-modifying putback()

Tags:

c++

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";

}
like image 415
Rick Avatar asked Mar 06 '23 10:03

Rick


2 Answers

Why s2.putback('Y') fails but s2.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.
like image 139
lubgr Avatar answered Mar 11 '23 11:03

lubgr


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 of gptr() (as determined by Traits::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.

like image 43
xskxzr Avatar answered Mar 11 '23 11:03

xskxzr