I'm going to keep this question very simple. I'm learning C++ and I've come across stringstreams. I understand that their main usage is to have variables input into them so they can later output the value they hold using str() as a string. My question is - what's the point of this? This sounds like a very fancy way of just concatenating a bunch of variables in a string object using the + operator. Does it have more to it than that or is it just so it confuses noobs and causes them to fail their exams?
-
Perfect example of the usefulness: http://stackoverflow.com/questions/236129/split-a-string-in-c – NathanOliver May 31 '16 at 18:25
-
So it's like concatenation, except it keeps track of the variables inputted as well? – Brogrammer May 31 '16 at 18:29
-
It can be also be used to un-concatenate a string. – NathanOliver May 31 '16 at 18:30
-
Awesome, thanks! Can I upvote you or something? – Brogrammer May 31 '16 at 18:32
-
No but you do have a couple of answers that you can consider for up voting or accepting. – NathanOliver May 31 '16 at 18:35
3 Answers
Well, one problem is that you cannot "concatenate a bunch of variables in a string using the + operator" (only other strings or char*s).
So, how are you going to turn all your objects into strings? Unlike Java, C++ does not have any to_string() member convention. On the other hand, every class interested in using iostream will define stream inserters (std::ostream& operator<<(std::ostream& os, const MyClass& foo)
and maybe std::istream& operator>>(std::istream& os, MyClass& foo)
.)
So, you use the stream inserters to convert objects to text. Sometimes you don't want to write to the console or to a file, but instead you want to store it as a string.
Also, using the iostream framework lets you use the manipulators to control precision, width, numerical base, and so on, instead of trying to do all that manually as you construct a string.
Now, that's not to say that the stringstream solution is ideal: in fact, a lot of libraries exist to do the same sort of task better (including at least Boost.Format, Boost.Convert, Boost.Lexical_Cast, and Boost.Spirit just in Boost.)

- 4,453
- 1
- 24
- 35
-
_"C++ does not have any to_string() member convention."_ Well, that's not [entirely true](http://en.cppreference.com/w/cpp/string/basic_string/to_string). – πάντα ῥεῖ May 31 '16 at 18:54
-
1@πάνταῥεῖ: By "member", I mean it's not standard to make a `to_string()` member function in all the classes you define, and the standard library doesn't try to use such functions. The fact that there are functions named `to_string` in the standard library isn't really germane. You could declare free `to_string` functions for your classes, to use generically via ADL, but AFAIK this isn't a convention yet either—it's much better to use boost::lexical_cast for that sort of thing. – Nick Matteo May 31 '16 at 18:58
-
2
If you have:
int a = 3;
std::string str = "hello";
MyObject obj;
Then:
std::string concat = a + str + obj;
std::string objstr = obj;
won't work, while:
std::stringstream stream;
stream << a << str << obj;
std::string concat = stream.str();
std::stringstream stream2;
stream2 << obj;
std::string objstr = stream2.str();
Will work (at least if MyObject
defines a operator<<
). That's the whole point of std::stringstream
: make it easy to redirect "anything" to a string.
Any object that can be redirected to a std::ostream
(std::fstream
, std::cout
...) can also be redirected to a std:::stringstream
(as it derives from ̀std::ostream
too). Then you just need to declare one std::ostream
redirection operator (operator<<
) and it can be used to redirect the object everywhere (file, console, but also string...).
The whole point is that you could declare a operator+
and operator+=
to make it possible to concatenate your object to a std::string
. But then, if you also wish to redirect it to a stream (file, cout), you'll have to declare 3 operators (operator+
, operator+=
and finally operator<<
for streams), all doing almost the same thing. In the end, thanks to std::stringstream
, having only one single operator (operator<<
) is enough to redirect to file, cout and string.

- 20,821
- 10
- 70
- 151
-
and with variadic templates we can have a function that uses that code with an arbitrary number of elements, and call it easily to concatenate any number of arguments of any types into a string. – coyotte508 May 31 '16 at 18:32
-
-
`operator<<` is simlar to `toString()`. ̀std::stringstream` makes it possible to use it with a ̀std::string` as target. – jpo38 May 31 '16 at 18:40
What's the point of stringstream?
It is a flexible and fast stream, and works as a simulator for other (comparatively) slow streams. I use stringstream for lots of different things.
My favorite use is for test. I create a std::istream and fill it with test data. This allows me to create the test data 'file' using the same editor with which I code (and no actual file polluting my work dir). Adding more test cases is remarkably less time consuming.
// 012345678901234567890123456789012345678901234567890
std::istringstream iss("7 ((23, 342), (17, 234), (335, 159), (10, 10))");
// ---|^^^^^^^|^v|vvvvvvv|v^|^^^^^^^^|^v|vvvvvv|^
// 1 2 3 4
// echo to user of test
std::cout << "Test Data Input: " << iss.str() << std::endl ;
// code under test starts here ...
int nTowns = 1;
char lparen0 = 2;
iss >> nTowns // NOTE : formatted input drops whitespace
>> lparen0;
// and continues with echo of post conversion
std::cout << " 0: " << nTowns << ' ' << lparen0 << std::endl;
// then more of the same - until record is completely read.
I have used stringstream to build a screen update, and use that dynamic changing string to 'measure' the banner width, and compute where to start the placement on the screen so that the banner is centered (or left, or right):
static void centerUpdateScreenBanner( uint64_t gen,
int pdMS,
int changes,
TC_t& tc)
{
// build contents of screen banner update
std::stringstream ss;
ss << std::setw(3) << pdMS << " "
<< std::setw(4) << gen << " "
<< std::setw(4) << changes;
// compute start column placement for centering
int rCol = tc.maxCol -
static_cast<int>(ss.str().size()) +
tc.DfltIndnt-1;
// send banner to terminal device for user info
tc.termRef << Ansi_t::gotoRC(0, rCol) // top right
<< ss.str() << std::flush;
}
Inside this link list, I use a stringstream to absorb and recursively concatenate list nodes info. While this builds recursively, other cout or cerr can proceed un-hindered - as if a 3rd channel.
std::string showR(void) {
std::stringstream ss;
ss << m_payload->show(); // this node
if(m_next) ss << m_next->showR(); // subsequent nodes
return (ss.str());
}
Summary: I have found std::stringstream to be very useful.

- 5,438
- 2
- 18
- 20