The standard way of converting between numbers and strings in C++11

In C++03 there was no standard way of converting numbers to strings. The best way to do that was using a std::stringstream:

int n = 42;
std::stringstream ss;
ss << n;
std::string s = ss.str();

One could put that into a more generic function that looks like this:

template <typename T>
std::string to_string(T const & value)
{
   std::stringstream ss;
   ss << value;
   return ss.str();
}

The opposite of converting a text to a number could look like this:

template <typename T>
T my_to_number(std::string const & text)
{
   T value;
   std::stringstream ss(text);
   ss >> value;
   return value;
}

Of course, there was also the option of using C functions such as itoa, sprintf or atoi (or their Microsoft secure version _itoa_s, sprintf_s).

C++11 provides several standard functions for converting numbers to strings and strings to numbers, all of them available in the <string> header.

For converting numbers to strings there are two new overloaded functions: to_string() and to_wstring(). They take one argument of various numeric types (int, long, long long, double, long double, etc.) and return either a std::string or a std::wstring with the number converted to text.

auto as = std::to_string(42);
auto ws = std::to_wstring(3.14);

These functions are actually just wrappers over sprintf and swprintf. According to the standard (section 21.5):

Each function returns a string object holding the character representation of the value of its argument that would be generated by calling sprintf(buf, fmt, val) with a format specifier of “%d”, “%u”, “%ld”, “%lu”, “%lld”, “%llu”, “%f”, “%f”, or “%Lf”, respectively, where buf designates an internal character buffer of sufficient size.

For the other way around of converting strings to numbers there are several overloaded methods (taking either a std::string or a std::wstring):

  • stoi: converts a string to a signed integer
  • stol: converts a string to a signed long
  • stoll: converts a string to a signed long long
  • stoul: converts a string to an unsigned long
  • stoull: converts a string to an unsigned long long
  • stof: converts a string to a float
  • stod: converts a string to a double
  • stold: converts a string to a long double
std::string as = "42";
std::wstring ws = "3.14"

auto n2 = std::stoi("42");
auto n3 = std::stoul(as);
auto n4 = std::stod(ws);

Functions stof, stod and stold are also just wrappers over strtod and strtold:

the first two functions call strtod(str.c_str(), ptr) and the third function calls strtold(str.c_str(), ptr). Each function returns the converted result, if any. The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx. If the function does not throw an exception and idx != 0, the function stores in *idx the index of the first unconverted element of str.

atoi() and atol() that convert a null-terminated byte-string (i.e. char*) to an integer or long were already available in header <cstdlib>. There is a new function available in this header called atoll() that converts a null-terminated byte string to a long long value.

auto n = std::atoll("42");

7 thoughts on “The standard way of converting between numbers and strings in C++11”

    • The standard says (21.5) for to_string:

      Each function returns a string object holding the character representation of the value of its argument that would be generated by calling sprintf(buf, fmt, val) with a format specifier of “%d”, “%u”, “%ld”, “%lu”, “%lld”, “%llu”, “%f”, “%f”, or “%Lf”, respectively, where buf designates an internal character buffer of sufficient size.

      and for stof, stod and stold:

      the first two functions call strtod(str.c_str(), ptr) and the third function calls strtold(str.c_str(), ptr). Each function returns the converted result, if any. The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx. If the function does not throw an exception and idx != 0, the function stores in *idx the index of the first unconverted element of str.

      Reply
      • It would be worth showing the full signature of the `stofoo()` functions, since without seeing e.g. `int stoi(const string& str, size_t *idx = 0, int base = 10);` the mention of `idx` in the standard extract doesn’t make sense.

        Reply
  1. Maybe it’s also worth mentioning that std::stoi and friends throw exceptions in case of invalid arguments (std::invalid_arguments) or under/overflows (std::out_of_range), as opposed to the C++98 std::atoi, which simply returns 0 in case of problems.

    Reply
  2. Coming back to the round-tripping of doubles: can the precision used for std::to_string(double) be set somewhere? otherwise you end up with the standard precision which is not suitable for round-tripping…

    Reply

Leave a Comment