Silviu-Marius Ardelean's blog

a software engineer's web log

Numeric type conversion to std::string and vice versa

In our real applications we have to convert from strings to integer or to real variables and vice versa (double/float/int variable to std::string).
We can realize these conversions using C style CRT function or we can try C++ approach via STL.
Unfortunately, current C standard libraries do not offer a complete support for any type of conversion. For instance, if we try to put an integer into a C++ string object (std::(w)string) using a well known function itoa() then we get next error:
[cpp]
int x1 = 230;
std::string s1;
itoa(x1, s1, 10);
[/cpp]
// error C2664: ‘itoa’ : cannot convert parameter 2 from ‘std::string’ to ‘char *’

A C style approach in order to avoid this error means using an intermediary buffer:
[cpp]
int x1 = 230;
std::string s1;
char szBuff[64]={0};
itoa(x1, szBuff, 10);
s1 = szBuff;
[/cpp]

Same story if we try to convert a std::string to an int:
[cpp]
std::string s3 = “442”;
int x3 = atoi(s3);
[/cpp]
// error C2664: ‘atoi’ : cannot convert parameter 1 from ‘std::string’ to ‘const char *’

In this case we can use c_str() in order to return a constant pointer to char.
[cpp]int x3 = atoi(s3.c_str());[/cpp]

An elegant way to get rid of such problems is to build two conversion function that use templates and C++ streams.
Base on this idea, I created a Sting2Numeric class that contains two static methods: Type2String() and String2Type().
[cpp]
class String2Numeric
{
public:

template
static xstring Type2String(TypeT x)
{
xostringstream o;
if (!(o << x)) throw BadConversion("Type2String(TypeT)"); return o.str(); } template
static TypeT String2Type(const xstring& s)
{
xistringstream i(s);
TypeT x;
if (!(i >> x))
throw BadConversion(“String2Type(TypeT)”);

return x;
}
};
[/cpp]

where BadConvertion is a std::runtime_error‘s derived class.
[cpp]
class BadConversion : public std::runtime_error {
public:
BadConversion(const std::string& s)
: std::runtime_error(s)
{ }
};[/cpp]

Because of ANSI and UNICODE project’s compatibility I defined few macros:
[cpp]
#ifdef _UNICODE
#define xstring std::wstring
#define xostringstream std::wostringstream
#define xistringstream std::wistringstream
#else
#define xstring std::string
#define xostringstream std::ostringstream
#define xistringstream std::istringstream
#endif
[/cpp]
Because of this compatibility I strongly recommend using a xstring alias instead of std::wstring or std::string.
When you want to convert an int, float, double, or other numerical type to a xstring in a C++ style you can use the Type2String() function. Vice versa, if you want to convert a xstring to these types you can use String2Type().

In order to avoid possible thrown exception I recommend to you using a try catch block whenever you’re using these functions. I prefer using xstring for string/wstring variables definition, too.
Here is a sample of using this class:
[cpp]
double y1 = 0.2312, y2 = 1.0123;
xstring s1 , s2;

try
{
s1 = String2Numeric::Type2String(y1);
s2 = String2Numeric::Type2String(x2);

#ifdef _UNICODE
xstring s3(L”43.52″);
#else
xstring s3(“43.52”);
#endif

x2 = String2Numeric::String2Type(s3);
y2 = String2Numeric::String2Type(s3);
}
catch (BadConversion &eBC)
{
std::cout << "An exception has been thrown: " << eBC.what() << std::endl; } [/cpp] The String2Numeric class can be extended. For instance, if the conversion throw an error then you can add detailed information in the exception message.

Download String2Numeric (1148 downloads) class.

, , , , ,
15/01/2011 at 6:25 PM Comments (0)