Using Stringstreams in C++ - Free Automatic Conversion
(Page 4 of 4 )
We've arrived at the part we've been waiting for: the conversion. C++ performs implicit conversion with some basic types, such as long to double and signed to unsigned or base* to derived* (pointer cast); however, it requires explicit conversion in the case of transforming a string to a string/sequence of characters.
There have been countless functions made just for this task, and even more once the wide character made its place in the world. The usage of this is somewhat worrying, as it offers no buffer overflow protection (you're in big trouble if the allocated space is too little and you are wasting memory if you are exaggerating). The type safety is also weak, because you could just define one in the format string and give another type.
Using this eventually leads to a source of constant bug possibility inside your application. All the while you are also offering a security hole, as a foreign program could sense the volatile property of the buffer and start to "play with it." Generally, it is a good idea to avoid the stdio library and all of its functions; use instead the sstream.
If you were paying close attention during the previous pages, you can figure out the solution on your own, but let me explain it nevertheless. The buzz is that stringstreams perform automatic low-level conversion while inserting a new value.
The place at which this is most probable is inside a char sequence. The opposite occurs once you extract a new value from the stream (consequently converting the text into what it can -- number, double, int, etcetera, or throwing an error by setting the fail flag if this is possible for text to number). If you are interested in this, just flip the extraction lines in the previous page as follows:
memoryStream >> text;
memoryStream >> dnubmer;
memoryStream >> number;
Moreover, observe that the int has been cast into double and the double into int:
alfa 10 10.122
Extraction:
10
alfa
10
Press any key to continue . . .
The stream will allocate for it as much memory as it needs, so feel free to add to it; it will destroy the object once that is released/destroyed. In order to prove this part of the article with examples, I decided to write a little cast function with templates that turned out like this (see below).
#include <iostream> // for accessing the console
#include <sstream>
#include <string>
using namespace std;
template<typename castTo, typename from>
castTo cast( from item)
{
stringstream temp;
castTo result; //call default constructor to initialize
temp << item;
temp >> result;
return result;
};
int main()
{
string text;
double number = 2.234;
cout <<setprecision(3) << number
<< " is not "<< cast<string>(number) << endl;
return 1;
}
The print part looks like this:
2.23 is not 2.234
Press any key to continue . . .
It works without problems. Observe that I reduced the precision print of the cin with a manipulator (doing so with the stringstream also would mean that only 2.23 will be converted into a string). This also demonstrates how to use the manipulators, while pointing out that the cast returned a string because otherwise it would have printed 2.24 to the console.
No need to specify a second parameter for the template; the compiler is smart enough to figure that out for us, we just need to point out what to transform. Now there is an easy and elegant cast!
With this we've reached the end of this part. Thank you for your attention; I encourage you to post your thoughts about this article here on the blog or join the DevHardware forums which is full of people who are eager to answer your question. If you rate my article that is also much appreciated and, of course, do not forget to: "Live with Passion!"
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |