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");
Its worth to mention that sto* functions throw exceptions if the input is invalid but in ato* functions, the behaviour is undefined for invalid inputs.
How strict is the standard for the implementation of std::to_string and std::stod – is it required to perfectly round-trip all doubles, so that double -> string -> double results in exactly the same binary as the original double?
The standard says (21.5) for to_string:
and for stof, stod and stold:
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.
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.
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…
Here is also an interesting article about many different ways how to convert a string to an int from last year. http://www.kumobius.com/2013/08/c-string-to-int/