Setting the content of a std::stringstream with str(const char*) has strange consequences

5.1k views Asked by At

I use std::stringstream extensively to generate code. I have run into some querious behavior when setting the content with the str() function followed by using the operator<<. Can someone explain this behavior to me. I would very much appreciate it - Thanks.

Example One:

std::stringstream ssa;
ssa.str("Setting string");
std::cout << ssa.str() << std::endl;
ssa << " adding to string";
std::cout << ssa.str() << std::endl;

Output:

Setting string

adding to string

Expected:

Setting string

Setting string adding to string

So after a bit of reading up on the documentation I found that I should set the open mode to ios_base::ate:

std::stringstream ssb(std::ios_base::ate);
ssb.str("Setting string");
std::cout << ssb.str() << std::endl;
ssb << " adding to string";
std::cout << ssb.str() << std::endl;

Output:

Setting string

Setting string

Again (or now) I would expect:

Setting string

Setting string adding to string

Why am I getting the results I am, and how do I get the result I want? E.i. Being able to set the initial string of a stringstream and the append to that string ?

I am aware that I can just set the content to the empty string("") and then only use the <<operator. This is in fact the workaround I am using. I just don't understand the observed behavior. And the workaround makes my code more messy.

2

There are 2 answers

9
Andreas DM On BEST ANSWER

You forgot to set flag mode: std::ios_base::out. This will work:

std::stringstream ssb(std::ios_base::out | std::ios_base::ate);
ssb.str("Setting string");
std::cout << ssb.str() << std::endl;
ssb << " adding to string";
std::cout << ssb.str() << std::endl;

Output:

Setting string
Setting string adding to string
2
David G On

The default open mode for a std::stringstream object is in | out. Using a different mode overrides these options. Since the stream cannot be written to, the insertion operator cannot be used to write to the stream. This is why str() gives the same output twice.

You need to manually open the stream in output mode as well:

std::stringstream ssb("Setting string", std::ios_base::out | std::ios_base::ate);

Live Demo

Alternatively, use an std::ostringstream, which initializes the internal std::stringbuf subobject with out | mode.

std::ostringstream("Setting string", std::ios_base::ate);

Live Demo