Search code examples
c++stringconstructorstringstreambidirectional

Why is stringstream ss(s) different from ss << s?


When I try to use stringstream like

#include <iostream>
#include <string>
#include <sstream>

int main() {
    std::string s = "Hello World Test";
    std::stringstream ss(s);

    std::string a, b;
    ss >> a >> b;
    std::cout << a << ' ' << b << std::endl; // Hello World

    ss << " Why Not";
    ss >> a >> b;
    std::cout << a << ' ' << b << std::endl; // Still Hello World

    std::string c, d;
    std::stringstream tt;
    tt << s;

    tt >> c >> d;
    std::cout << c << ' ' << d << std::endl; // Hello World

    tt << " Now Yes";
    tt >> c >> d;  // print Now Yes
    std::cout << c << ' ' << d << std::endl; // Test Now
}

Does any one know why stringsteam construct behaves differently?

I expect stringstream can go in and out freely. But it seems not. If used in one direction, I dont any problem.


Solution

  • When you create a stringstream from a string like this, the default mode is in|out -- meaning input or output is allowed, BUT all the pointers default to pointing at the beginning of the buffer. So when you write into the stringstream with << it overwrites the string there, and your reads at the end will just run off the end.

    If you instead do

    std::stringstream ss(s, std::ios_base::in | std::ios_base::out | std::ios_base::ate);
    

    (adding the 'at the end' flag) it will work more like you expect, starting the pptr at the end of the initial string.

    Why this is not the default is a bit of a mystery (probably just a mistake in the earliest implementations that got codified in the standard as noone wanted to break backward compatibility with this misfeature).