官术网_书友最值得收藏!

Converting between numeric and string types

Converting between number and string types is a ubiquitous operation. Prior to C++11, there was little support for converting numbers to strings and back, so developers had to resort mostly to type-unsafe functions, and they usually wrote their own utility functions in order to avoid writing the same code over and over again. With C++11, the standard library provides utility functions for converting between numbers and strings. In this recipe, you will learn how to convert between numbers and strings and the other way around using modern C++ standard functions.

Getting ready

All the utility functions mentioned in this recipe are available in the <string> header.

How to do it...

Use the following standard conversion functions when you need to convert between numbers and strings:

  • To convert from an integer or floating-point type to a string type, use std::to_string() or std::to_wstring(), as shown in the following code snippet:
    auto si = std::to_string(42);      // si="42"
    auto sl = std::to_string(42L);     // sl="42"
    auto su = std::to_string(42u);     // su="42"
    auto sd = std::to_wstring(42.0);   // sd=L"42.000000"
    auto sld = std::to_wstring(42.0L); // sld=L"42.000000"
    
  • To convert from a string type to an integer type, use std::stoi(), std::stol(), std::stoll(), std::stoul(), or std::stoull(), as shown in the following code snippet:
    auto i1 = std::stoi("42");                 // i1 = 42
    auto i2 = std::stoi("101010", nullptr, 2); // i2 = 42
    auto i3 = std::stoi("052", nullptr, 8);    // i3 = 42
    auto i4 = std::stoi("0x2A", nullptr, 16);  // i4 = 42
    
  • To convert from a string type to a floating-point type, use std::stof(), std::stod(), or std::stold(), as shown in the following code snippet:
    // d1 = 123.45000000000000
    auto d1 = std::stod("123.45");
    // d2 = 123.45000000000000
    auto d2 = std::stod("1.2345e+2");
    // d3 = 123.44999980926514
    auto d3 = std::stod("0xF.6E6666p3");
    

How it works...

To convert an integral or floating-point type to a string type, you can use either the std::to_string() function (which converts to a std::string) or the std::to_wstring() function (which converts to a std::wstring). These functions are available in the <string> header and have overloads for signed and unsigned integer and real types. They produce the same result as std::sprintf() and std::swprintf() would produce when called with the appropriate format specifier for each type. The following code snippet lists all the overloads of these two functions:

std::string to_string(int value);
std::string to_string(long value);
std::string to_string(long long value);
std::string to_string(unsigned value);
std::string to_string(unsigned long value);
std::string to_string(unsigned long long value);
std::string to_string(float value);
std::string to_string(double value);
std::string to_string(long double value);
std::wstring to_wstring(int value);
std::wstring to_wstring(long value);
std::wstring to_wstring(long long value);
std::wstring to_wstring(unsigned value);
std::wstring to_wstring(unsigned long value);
std::wstring to_wstring(unsigned long long value);
std::wstring to_wstring(float value);
std::wstring to_wstring(double value);
std::wstring to_wstring(long double value);

When it comes to the opposite conversion, there is an entire set of functions that have a name with the format ston (string to number), where n stands for i (integer), l (long), ll (long long), ul (unsigned long), or ull (unsigned long long). The following list shows all these functions, each of them with two overloads—one that takes an std::string and one that takes an std::wstring as the first parameter:

int stoi(const std::string& str, std::size_t* pos = 0,
 int base = 10);
int stoi(const std::wstring& str, std::size_t* pos = 0,
 int base = 10);
long stol(const std::string& str, std::size_t* pos = 0,
 int base = 10);
long stol(const std::wstring& str, std::size_t* pos = 0,
 int base = 10);
long long stoll(const std::string& str, std::size_t* pos = 0,
 int base = 10);
long long stoll(const std::wstring& str, std::size_t* pos = 0,
 int base = 10);
unsigned long stoul(const std::string& str, std::size_t* pos = 0,
 int base = 10);
unsigned long stoul(const std::wstring& str, std::size_t* pos = 0,
 int base = 10);
unsigned long long stoull(const std::string& str,
 std::size_t* pos = 0, int base = 10);
unsigned long long stoull(const std::wstring& str,
 std::size_t* pos = 0, int base = 10);
float stof(const std::string& str, std::size_t* pos = 0);
float stof(const std::wstring& str, std::size_t* pos = 0);
double stod(const std::string& str, std::size_t* pos = 0);
double stod(const std::wstring& str, std::size_t* pos = 0);
long double stold(const std::string& str, std::size_t* pos = 0);
long double stold(const std::wstring& str, std::size_t* pos = 0);

The way the string to integral type functions work is by discarding all white spaces before a non-whitespace character, then taking as many characters as possible to form a signed or unsigned number (depending on the case), and then converting that to the requested integral type (stoi() will return an integer, stoul() will return an unsigned long, and so on). In all the following examples, the result is the integer 42, except for the last example, where the result is -42:

auto i1 = std::stoi("42");             // i1 = 42
auto i2 = std::stoi(" 42");          // i2 = 42
auto i3 = std::stoi(" 42fortytwo");  // i3 = 42
auto i4 = std::stoi("+42");            // i4 = 42
auto i5 = std::stoi("-42");            // i5 = -42

A valid integral number may consist of the following parts:

  • A sign, plus (+) or minus (-) (optional)
  • Prefix 0 to indicate an octal base (optional)
  • Prefix 0x or 0X to indicate a hexadecimal base (optional)
  • A sequence of digits

The optional prefix 0 (for octal) is applied only when the specified base is 8 or 0. Similarly, the optional prefix 0x or 0X (for hexadecimal) is applied only when the specified base is 16 or 0.

The functions that convert a string to an integer have three parameters:

  • The input string.
  • A pointer that, when not null, will receive the number of characters that were processed. This can include any leading whitespaces that were discarded, the sign, and the base prefix, so it should not be confused with the number of digits the integral value has.
  • A number indicating the base; by default, this is 10.

The valid digits in the input string depend on the base. For base 2, the only valid digits are 0 and 1; for base 5, they are 01234. For base 11, the valid digits are 0-9 and the characters A and a. This continues until we reach base 36, which has the valid characters 0-9, A-Z, and a-z.

The following are additional examples of strings with numbers in various bases converted to decimal integers. Again, in all cases, the result is either 42 or -42:

auto i6 = std::stoi("052", nullptr, 8);
auto i7 = std::stoi("052", nullptr, 0);
auto i8 = std::stoi("0x2A", nullptr, 16);
auto i9 = std::stoi("0x2A", nullptr, 0);
auto i10 = std::stoi("101010", nullptr, 2);
auto i11 = std::stoi("22", nullptr, 20);
auto i12 = std::stoi("-22", nullptr, 20);
auto pos = size_t{ 0 };
auto i13 = std::stoi("42", &pos);      // pos = 2
auto i14 = std::stoi("-42", &pos);     // pos = 3
auto i15 = std::stoi(" +42dec", &pos);// pos = 5

An important thing to note is that these conversion functions throw an exception if the conversion fails. There are two exceptions that can be thrown:

  • std::invalid_argument: If the conversion cannot be performed:
    try
    {
      auto i16 = std::stoi("");
    }
    catch (std::exception const & e)
    {
      // prints "invalid stoi argument"
      std::cout << e.what() << '\n';
    }
    
  • std::out_of_range: If the converted value is outside the range of the result type (or if the underlying function sets errno to ERANGE):
    try
    {
      // OK
      auto i17 = std::stoll("12345678901234");
      // throws std::out_of_range
      auto i18 = std::stoi("12345678901234");
    }
    catch (std::exception const & e)
    {
      // prints "stoi argument out of range"
      std::cout << e.what() << '\n';
    }
    

The other set of functions that convert a string to a floating-point type is very similar, except that they don't have a parameter for the numeric base. A valid floating-point value can have different representations in the input string:

  • Decimal floating-point expression (optional sign, sequence of decimal digits with optional point, optional e or E, followed by exponent with optional sign).
  • Binary floating-point expression (optional sign, 0x or 0X prefix, sequence of hexadecimal digits with optional point, optional p or P, followed by exponent with optional sign).
  • Infinity expression (optional sign followed by case-insensitive INF or INFINITY).
  • A non-number expression (optional sign followed by case-insensitive NAN and possibly other alphanumeric characters).

The following are various examples of converting strings to doubles:

auto d1 = std::stod("123.45");         // d1 = 123.45000000000000
auto d2 = std::stod("+123.45");        // d2 = 123.45000000000000
auto d3 = std::stod("-123.45");        // d3 = -123.45000000000000
auto d4 = std::stod(" 123.45");       // d4 = 123.45000000000000
auto d5 = std::stod(" -123.45abc");   // d5 = -123.45000000000000
auto d6 = std::stod("1.2345e+2");      // d6 = 123.45000000000000
auto d7 = std::stod("0xF.6E6666p3");   // d7 = 123.44999980926514
auto d8 = std::stod("INF");            // d8 = inf
auto d9 = std::stod("-infinity");      // d9 = -inf
auto d10 = std::stod("NAN");           // d10 = nan
auto d11 = std::stod("-nanabc");       // d11 = -nan

The floating-point base 2 scientific notation, seen earlier in the form 0xF.6E6666p3, is not the topic of this recipe. However, for a clear understanding, a short description is provided; but it is recommended that you look at additional references for details (such as https://en.cppreference.com/w/cpp/language/floating_literal). A floating-point constant in the base 2 scientific notation is composed of several parts:

  • The hexadecimal prefix 0x.
  • An integer part, which in this example was F, which in decimal is 15.
  • A fractional part, which in this example was 6E6666, or 011011100110011001100110 in binary. To convert that into decimal, we need to add inverse powers of two: 1/4 + 1/8 + 1/32 + 1/64 + 1/128 + ....
  • A suffix, representing a power of 2; in this example, p3 means 2 at the power of 3.

The value of the decimal equivalent is determined by multiplying the significant (composed of the integer and fractional parts) and the base at the power of the exponent.

For the given hexadecimal base 2 floating-point literal, the significant is 15.4312499... (please note that digits after the seventh one are not shown), the base is 2, and the exponent is 3. Therefore, the result is 15.4212499... * 8, which is 123.44999980926514.

See also

  • Limits and other properties of numeric types to learn about the minimum and maximum values, as well as the other properties of numerical types
主站蜘蛛池模板: 临朐县| 富裕县| 沅陵县| 焦作市| 额敏县| 进贤县| 都江堰市| 宁德市| 普洱| 海门市| 景泰县| 靖宇县| 华阴市| 都兰县| 彭阳县| 西乌珠穆沁旗| 日喀则市| 扎兰屯市| 惠东县| 巩义市| 大英县| 资阳市| 从江县| 奉节县| 江西省| 广东省| 溆浦县| 平和县| 通州市| 澳门| 抚顺县| 海盐县| 巴彦淖尔市| 张家口市| 太仆寺旗| 云阳县| 阿克苏市| 大英县| 宜阳县| 金秀| 株洲县|