Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can I convert a {int, double, string, foo} into a string or vice versa?

Programming

How can I convert a {int, double, string, foo} into a string or vice versa?

by  chipperMDW  Posted    (Edited  )
While there is a set of old, C-style functions for doing this, they're limited in usefulness. There's an atoi (which converts an ASCII character to an integer), but no corresponding itoa (at least not a Standard one). With this kind of system, you'd need one function to convert each supported type to each other supported type, or at least from each supported type to some accepted intermediate type. This doesn't scale well, obviously.


C provides an alternative to these functions, sprintf and sscanf, which is a better option.

The sprintf function works like its more well-known cousin, printf, except that instead of putting its "output" on the console, it puts it into a (C-style) string, which you can then manipulate within your program. In other words, this lets you "output" an integer (or any other basic type) into a string, which subsequently contains the same string of characters that would have been output onto the console, such as a '4' followed by a '2' for the integer 42.

The sscanf function is the reverse: you use it to read values from a C-style string as if the string contained characters entered at the console for the scanf function. For example, the integer 42 would be extracted from the character '4' followed by the character '2' in a string.

These two functions are much more versatile than atoi and friends, but they still have limitations. They require that you work with C-style strings, which is never fun. Barring any implementation-specific (and therefore non-Standard) extensions to the C I/O system, sprintf and sscanf functions are also only effective for built-in types. Finally, they're not type-safe; nothing stops you from trying to output a floating point number as an octal integer if you make a typo in your format string.


The "preferred" way to do these kinds of conversions is through C++'s rich I/O system. The C++ equivalent of s{print, scan}f are the stringstreams: stringstream, istringstream, and ostringstream. (There were also some strstreams, but they're deprectated... we don't speak of them).

The general concept is the same, but stringstreams use objects of type string, which are much easier to work with than objects of type char* (C-style strings). They're also type-safe and extensible. All plusses.

An istringstream serves as input (hence the "i"). Much as you'd say "cin >> myNum;" to read an integer from the console, you can say "str_in >> myNum;" to read an integer from that istringstream's buffer (a string). To get that buffer into the stream in the first place, you call "str_in.str( the_string_with_the_integer );".

An ostringstream serves as "output." Just like writing an integer to the console with "cout << 666;" you can write an integer to an ostringstream with "str_out << 666;". To get that string out, you just call "str_out.str()", which returns the buffer.


A stringstream is a combination of {i, o}stringstream. It serves as both input and output. That means that, instead of setting its buffer as with istringstream, you can just shove something in there as if it were an ostringstream. You can then subsequently extract what that ended up as into something else. In other words, you can convert something into something else if something's output could be used as something else's input (also assuming something and something else have conventional I/O operators defined). In more other words, this is a powerful and versatile way of converting stuff to other stuff: shove stuff into a stringstream, then shove the contents of stringstream into other stuff.


Finally, we have a pretty good solution to the problem. The only bad thing about using a stringstream is that you have to use a stringstream. Every time you want to convert something, you've gotta make a new stringstream, or grab an existing one, and do your stuff. Then you have the stringstream lying around while you're not really using it anymore.

Someone out there who's still reading this just said, "Why can't you just encapsulate that process in some kind of function?" Well, you could, but you shouldn't because if you did, you'd be reinventing the wheel.


Boost (www.boost.org) has a nice tool called lexical_cast that does just that. It's a function template that you call by giving it a template argument and a regular argument. Internally, it creates a stringstream, shoves the regular argument into that, pops that out into an object whose type is that specified by the template argument, then returns that object. It also does some error checking underneath.

The end result is that you can just lexical_cast anything to anything else if their output and input are compatible, and if they have the standard operators defined.


There are also other non-Standard ways to perform these types of conversions. Many vendor-specific string classes provide member functions to convert to or from other types. The solutions described above are those that should be applicable to any Standard and reasonably recent C++ installation, and so should work anywhere (with the exception of lexical_cast, for which you'd need only a few extra (free) files from Boost).
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top