C++ stringstream class

Red Squirrel

[H]F Junkie
Joined
Nov 29, 2009
Messages
9,211
I discovered this not too long ago, and it makes it 100 times easier to concatenate strings and ints together. Great for formulating SQL queries and such without the need to call int to string type functions.

I have never seen this in any tutorial or any examples when researching stuff. Is there any reason NOT to use this class when formulating strings? It seems like a HUGE life saver to me.

ex:

Code:
stringstream ss;

ss<<"SELECT * FROM "<<db.tableprefix<<"_users WHERE regdate>"<<(curtime-3600)<<" limit 100";

query(ss.str());

Instead of:

Code:
string ss;

ss="SELECT * FROM " + db.tableprefix + "_users WHERE regdate>" + ConvertInt2Str(curtime-3600) + " limit 100";

query(ss);

Where ConvertInt2Str() would be a custom function somewhere with some sprintf stuff. With ss, I don't need to make a custom function like this.
 
Readability is about the same between using a string and a stringstream.

With stringstream (you can use just ostringstream in your case as you only have to shove stuff into it), you have all the data in the stream and then you have to use .str() which creates a copy of that data as a string.

If you use just a string (and += each of the strings into it separately to avoid extra copies of things), the string way might be more memory efficient.

As for building strings, stringstreams are supposed to be faster. But, you'd have to check to make sure it is in your case.

Where ConvertInt2Str() would be a custom function somewhere with some sprintf stuff.

Well, you'd normally use:

Code:
string to_string(const int& i) {
    ostringstream ss;
    ss << i;
    return ss.str();
}

But, yeh, you could use something like:

Code:
string to_string(const int& i) {
    char s[100];
    return (sprintf(s, "%d", i) < 0) ? "" : s;
}

Using it with the string method might be more efficient overall than just using a stringstream. But, don't know for sure.

Given that, if you like the stringstream way and it doesn't create any problems for you, then you should use it.
 
your first example actually looks worse because there is no space between the operators.
 
Well that was just written quickly, sometimes I break it down into multiple statements. But is this a good way of doing it? Not formatwise, just, code wise. Like, is there a performance or other issue? SQL Injection concerns aside, of course. Not a concern for this particular app. Normally I sanitize my data as soon as it is gotten from the user, so at this stage it would already be sanitized. In this case it's not user data.

Like for a real life example, here's one that I have:

Code:
	stringstream query;
	query<<"SELECT * FROM shards WHERE sactive=1 AND sofflineinactive=0 AND spolling=0 AND (slaststatupdate+";
	query<<(POLL_INTERVAL_SECS/60);
	query<<")<"<<curtime.GetDate("U");
	query<<" ORDER BY slaststatupdate ASC LIMIT "<<amt<<";";
		
	if(!m_con->DoQuery(query.str()))
	{
		Logger::Log("query shards query error: " + m_con->GetError(true));
		return ret;
	}
 
Red Squirrel, every time you would otherwise mention the word "performance", throw a glass of ice water in your face. Do that until you stop thinking about that.

Your goal of "performance" is causing you to waste enormous amounts of time, make insecure code, and probably slower code, too.
 
Red Squirrel, every time you would otherwise mention the word "performance", throw a glass of ice water in your face. Do that until you stop thinking about that.

Your goal of "performance" is causing you to waste enormous amounts of time, make insecure code, and probably slower code, too.

^This^

"SQL Injection concerns aside, of course. Not a concern for this particular app."
Have you constructed a threat model, checked all input and output vectors, and made sure that's actually a true statement?

Generally, for SQL from code, I'd use a known and vetted library with parameter binding, rather than manually constructing the strings. There are just too many things that could go wrong trying to roll your own.

If you're not going to follow Whatisname's suggestion for cold water, take a shot. Soon you won't _CARE_ about performance, and maybe you'll get somewhere ;)
 
Red Squirrel, every time you would otherwise mention the word "performance", throw a glass of ice water in your face. Do that until you stop thinking about that.

Your goal of "performance" is causing you to waste enormous amounts of time, make insecure code, and probably slower code, too.

Ok I just used that as an example. Instead of going around my question, all I'm asking is this:

Is there anything wrong with using the stringstream class to format strings that may have different types. Or is there a better way?

I'm already using the mysql++ class, so I did not roll anything on my own. All I'm asking is if stringstream is the way to go to format strings so I can do a query. And again mysql is just an example of it's use. There are many different situations in programming where you want to pass a string of data, and some of that data may have numbers in it, so you want to just turn it into one big string so you can pass it to whatever function you're dealing with.
 
^This^

"SQL Injection concerns aside, of course. Not a concern for this particular app."
Have you constructed a threat model, checked all input and output vectors, and made sure that's actually a true statement?


For that particular app, there is no user inputted data. It creates statistics based on user inputted data, but these stats are all numbers, these numbers are then inserted into the database, or otherwise manipulated. And again, that was just an example. I'm asking a general question on whether or not stringstream is a good way to concatenate strings and ints together, or if there is a better way.
 
Readability is about the same between using a string and a stringstream.

With stringstream (you can use just ostringstream in your case as you only have to shove stuff into it), you have all the data in the stream and then you have to use .str() which creates a copy of that data as a string.

If you use just a string (and += each of the strings into it separately to avoid extra copies of things), the string way might be more memory efficient.

As for building strings, stringstreams are supposed to be faster. But, you'd have to check to make sure it is in your case.



Well, you'd normally use:

Code:
string to_string(const int& i) {
    ostringstream ss;
    ss << i;
    return ss.str();
}

But, yeh, you could use something like:

Code:
string to_string(const int& i) {
    char s[100];
    return (sprintf(s, "%d", i) < 0) ? "" : s;
}

Using it with the string method might be more efficient overall than just using a stringstream. But, don't know for sure.

Given that, if you like the stringstream way and it doesn't create any problems for you, then you should use it.

I missed this post at first, thanks for a straight out answer. That's pretty much what I wanted. So I'll stick to stringstream then. Just odd I've never seen it in any tutorials before, so figured maybe there was a reason not to use it. If it can do what my custom function was doing, then I rather use this instead of something custom.
 
boost::format

Code:
#include <iostream>
#include <string>
#include <boost/format.hpp>
using namespace std;
using namespace boost;

int main() {
    cout << format("%1% %2% %3% %4% %5%") % 1 % "2" % '3' % string("4") % 5.0 << endl;
    format fmt("%1% %2% %3%");
    fmt.exceptions(boost::io::no_error_bits);
    fmt % 1 % 2;
    cout << fmt << endl;
    const string s = fmt.str();
    cout << s << endl;
}

is a lot more fun though.

In addition to using the %n% syntax, you can use printf-like syntax for the format string.

See the documentation and make sure to look at the performance section.

Also, for when you just need to convert types, look at lexical_cast. It's like a wrapper around stringstream.

Boost is mostly header-only so you can just include and use it for the examples above. There are a few things in boost (like regex and filesystem) that require you to also build libs though. I've done it for mingw before. It wasn't too hard.

I use this mingw distro, which has boost included and the libs already built for it. So, for me, using boost is easy.
 
Last edited:
boost::format

Code:
#include <iostream>
#include <string>
#include <boost/format.hpp>
using namespace std;
using namespace boost;

int main() {
    cout << format("%1% %2% %3% %4% %5%") % 1 % "2" % '3' % string("4") % 5.0 << endl;
    format fmt("%1% %2% %3%");
    fmt.exceptions(boost::io::no_error_bits);
    fmt % 1 % 2;
    cout << fmt << endl;
    const string s = fmt.str();
    cout << s << endl;
}

is a lot more fun though.

In addition to using the %n% syntax, you can use printf-like syntax for the format string.

See the documentation and make sure to look at the performance section.

Also, for when you just need to convert types, look at lexical_cast. It's like a wrapper around stringstream.

Boost is mostly header-only so you can just include and use it for the examples above. There are a few things in boost (like regex and filesystem) that require you to also build libs though. I've done it for mingw before. It wasn't too hard.

I use this mingw distro, which has boost included and the libs already built for it. So, for me, using boost is easy.

you had to go and mention boost::format didn't you.. it is SLOOOOOWWWWWWWW

If you want a fast (the fastest I have found) output library, use FastFormat.

http://www.fastformat.org/

Newer versions on sourceforge.net (the other place I was meaning to mention to the OP for good code examples)

http://sourceforge.net/projects/fastformat/
 
I always just used sprintf
Code:
char str[512];
sprintf(str, "int: %d float %f string %s", 42, 3.1415f, "Yo");
Bonus points if you use sprintf_s, and even more for swprint_s. It's always fast enough.
 
I always just used sprintf
Code:
char str[512];
sprintf(str, "int: %d float %f string %s", 42, 3.1415f, "Yo");
Bonus points if you use sprintf_s, and even more for swprint_s. It's always fast enough.

Not if you are outputting to a file or outputting huge amounts of data to the screen.
 
Back
Top