Converting a String to a Numeric Type

Problem

You have numbers in string format, but you need to convert them to a numeric type, such as an int or float.

Solution

You can do this in one of two ways, with standard library functions or with the lexical_cast class in Boost (written by Kevlin Henney). The standard library functions are cumbersome and unsafe, but they are standard, and in some cases, you need them, so I present them as the first solution. lexical_cast is safer, easier to use, and just more fun, so I present it in the discussion.

The functions strtol, strtod, and strtoul, defined in , convert a null-terminated character string to a long int, double, or unsigned long. You can use them to convert numeric strings of any base to a numeric type. The code in Example 3-1 demonstrates a function, hex2int, that you can use for converting a hexadecimal string to a long.

Example 3-1. Converting number strings to numbers

#include 
#include 
#include 

using namespace std;

long hex2int(const string& hexStr) {
 char *offset;
 if (hexStr.length( ) > 2) {
 if (hexStr[0] == '0' && hexStr[1] == 'x') {
 return strtol(hexStr.c_str( ), &offset, 0);
 }
 }
 return strtol(hexStr.c_str( ), &offset, 16);
}

int main( ) {
 string str1 = "0x12AB";
 cout << hex2int(str1) << endl;
 string str2 = "12AB";
 cout << hex2int(str2) << endl;
 string str3 = "QAFG";
 cout << hex2int(str3) << endl;
}

Here's the output from this program:

4779
4779
0

The first two strings both contain the hexadecimal number 12AB. The first of the two has the 0x prefix, while the second doesn't. The third string doesn't contain a valid hexadecimal number; the function simply returns 0 in that case.

Discussion

Some people might be inclined to write their own function that converts hexadecimal numbers to integers. But why reinvent the wheel? The standard library already provides this functionality. Example 3-1 provides a wrapper function to simplify the calling of strtol. The strtol function is actually an older function from the C library, and it requires you to pass in a pointer to a null-terminated string, along with the address of another character pointer; this latter pointer receives the address of where the parsing ended. In C++, however, most people prefer to work with the more powerful string class rather than the older-style character pointers. Thus, this hex2int function takes a string parameter.

The strtol function is a bit odd in that it allows you to use two different methods for specifying a base of 16; you can either pass 16 as a third parameter to the function; or, you can pass 0 for the base while preceding your string with the characters 0x (just as you would do for specifying hexadecimal constants in your code; however, remember that with strtol, you're passing a string).

Example 3-1 allows you to use either method. If you pass a string such as 0x12AB, the function will detect the 0x and pass it right on to strtol, with 0 for the third parameter. Otherwise, the function will pass the string with 16 for the third parameter.

strtol and strtoul work the same way; the only difference is the return type. strtod is similar, but does not allow you to specify a base.

These old-school C functions aren't the only way to convert strings to numbers. The Boost project provides a conversion class lexical_cast that does the same thing for numeric strings of base 10. Example 3-2 shows how to use it.

Example 3-2. Using lexical_cast

#include 
#include 
#include 

using namespace std;

int main( ) {
 string str1 = "750";
 string str2 = "2.71";
 string str3 = "0x7FFF";
 try {
 cout << boost::lexical_cast(str1) << endl;
 cout << boost::lexical_cast(str2) << endl;
 cout << boost::lexical_cast(str3) << endl;
 }
 catch (boost::bad_lexical_cast& e) {
 cerr << "Bad cast: " << e.what( ) << endl;
 }
}

The output from Example 3-2 is:

750
2.71
Bad cast: bad lexical cast: source type value could not be
interpreted as target

You can see that it throws an exception for the last value, which is a hexadecimal number. If you have to convert numbers of a base other than 10, you will have to use the strtol functions.

There are versions of the strtol functions for wide characters, too. The wide character equivalent to strtol is wcstol and it is declared in . The equivalent functions for strtod and strtoul are wcstod and wcstoul. Each of these functions the same way, except that the parameters that are char*'s in the narrow character functions are wchar_t*'s in the wide character functions.

See Also

Recipe 3.2

Building C++ Applications

Code Organization

Numbers

Strings and Text

Dates and Times

Managing Data with Containers

Algorithms

Classes

Exceptions and Safety

Streams and Files

Science and Mathematics

Multithreading

Internationalization

XML

Miscellaneous

Index



C++ Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2006
Pages: 241

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net