How to convert a number to string and vice versa in C++

161,359

Solution 1

Update for C++11

As of the C++11 standard, string-to-number conversion and vice-versa are built in into the standard library. All the following functions are present in <string> (as per paragraph 21.5).

string to numeric

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

Each of these take a string as input and will try to convert it to a number. If no valid number could be constructed, for example because there is no numeric data or the number is out-of-range for the type, an exception is thrown (std::invalid_argument or std::out_of_range).

If conversion succeeded and idx is not 0, idx will contain the index of the first character that was not used for decoding. This could be an index behind the last character.

Finally, the integral types allow to specify a base, for digits larger than 9, the alphabet is assumed (a=10 until z=35). You can find more information about the exact formatting that can parsed here for floating-point numbers, signed integers and unsigned integers.

Finally, for each function there is also an overload that accepts a std::wstring as it's first parameter.

numeric to string

string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long long val);
string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);

These are more straightforward, you pass the appropriate numeric type and you get a string back. For formatting options you should go back to the C++03 stringsream option and use stream manipulators, as explained in an other answer here.

As noted in the comments these functions fall back to a default mantissa precision that is likely not the maximum precision. If more precision is required for your application it's also best to go back to other string formatting procedures.

There are also similar functions defined that are named to_wstring, these will return a std::wstring.

Solution 2

How to convert a number to a string in C++03

  1. Do not use the itoa or itof functions because they are non-standard and therefore not portable.
  2. Use string streams

     #include <sstream>  //include this to use string streams
     #include <string> 
    
    int main()
    {    
        int number = 1234;
    
        std::ostringstream ostr; //output string stream
        ostr << number; //use the string stream just like cout,
        //except the stream prints not to stdout but to a string.
    
        std::string theNumberString = ostr.str(); //the str() function of the stream 
        //returns the string.
    
        //now  theNumberString is "1234"  
    }
    

    Note that you can use string streams also to convert floating-point numbers to string, and also to format the string as you wish, just like with cout

    std::ostringstream ostr;
    float f = 1.2;
    int i = 3;
    ostr << f << " + " i << " = " << f + i;   
    std::string s = ostr.str();
    //now s is "1.2 + 3 = 4.2" 
    

    You can use stream manipulators, such as std::endl, std::hex and functions std::setw(), std::setprecision() etc. with string streams in exactly the same manner as with cout

    Do not confuse std::ostringstream with std::ostrstream. The latter is deprecated

  3. Use boost lexical cast. If you are not familiar with boost, it is a good idea to start with a small library like this lexical_cast. To download and install boost and its documentation go here. Although boost isn't in C++ standard many libraries of boost get standardized eventually and boost is widely considered of the best C++ libraries.

    Lexical cast uses streams underneath, so basically this option is the same as the previous one, just less verbose.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       float f = 1.2;
       int i = 42;
       std::string sf = boost::lexical_cast<std::string>(f); //sf is "1.2"
       std::string si = boost::lexical_cast<std::string>(i); //sf is "42"
    }
    

How to convert a string to a number in C++03

  1. The most lightweight option, inherited from C, is the functions atoi (for integers (alphabetical to integer)) and atof (for floating-point values (alphabetical to float)). These functions take a C-style string as an argument (const char *) and therefore their usage may be considered a not exactly good C++ practice. cplusplus.com has easy-to-understand documentation on both atoi and atof including how they behave in case of bad input. However the link contains an error in that according to the standard if the input number is too large to fit in the target type, the behavior is undefined.

    #include <cstdlib> //the standard C library header
    #include <string>
    int main()
    {
        std::string si = "12";
        std::string sf = "1.2";
        int i = atoi(si.c_str()); //the c_str() function "converts" 
        double f = atof(sf.c_str()); //std::string to const char*
    }
    
  2. Use string streams (this time input string stream, istringstream). Again, istringstream is used just like cin. Again, do not confuse istringstream with istrstream. The latter is deprecated.

    #include <sstream>
    #include <string>
    int main()
    {
       std::string inputString = "1234 12.3 44";
       std::istringstream istr(inputString);
       int i1, i2;
       float f;
       istr >> i1 >> f >> i2;
       //i1 is 1234, f is 12.3, i2 is 44  
    }
    
  3. Use boost lexical cast.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       std::string sf = "42.2"; 
       std::string si = "42";
       float f = boost::lexical_cast<float>(sf); //f is 42.2
       int i = boost::lexical_cast<int>(si);  //i is 42
    }       
    

    In case of a bad input, lexical_cast throws an exception of type boost::bad_lexical_cast

Solution 3

In C++17, new functions std::to_chars and std::from_chars are introduced in header charconv.

std::to_chars is locale-independent, non-allocating, and non-throwing.

Only a small subset of formatting policies used by other libraries (such as std::sprintf) is provided.

From std::to_chars, same for std::from_chars.

The guarantee that std::from_chars can recover every floating-point value formatted by to_chars exactly is only provided if both functions are from the same implementation

 // See en.cppreference.com for more information, including format control.
#include <cstdio>
#include <cstddef>
#include <cstdlib>
#include <cassert>
#include <charconv>

using Type =  /* Any fundamental type */ ;
std::size_t buffer_size = /* ... */ ;

[[noreturn]] void report_and_exit(int ret, const char *output) noexcept 
{
    std::printf("%s\n", output);
    std::exit(ret);
}
void check(const std::errc &ec) noexcept
{
    if (ec ==  std::errc::value_too_large)
        report_and_exit(1, "Failed");
}
int main() {
    char buffer[buffer_size];        
    Type val_to_be_converted, result_of_converted_back;

    auto result1 = std::to_chars(buffer, buffer + buffer_size,  val_to_be_converted);
    check(result1.ec);
    *result1.ptr = '\0';

    auto result2 = std::from_chars(buffer, result1.ptr, result_of_converted_back);
    check(result2.ec);

    assert(val_to_be_converted == result_of_converted_back);
    report_and_exit(0, buffer);
}

Although it's not fully implemented by compilers, it definitely will be implemented.

Share:
161,359
Armen Tsirunyan
Author by

Armen Tsirunyan

Updated on October 17, 2020

Comments

  • Armen Tsirunyan
    Armen Tsirunyan over 3 years

    Since this question gets asked about every week, this FAQ might help a lot of users.

    • How to convert an integer to a string in C++

    • how to convert a string into an integer in C++

    • how to convert a floating-point number to a string in C++

    • how to convert a string to a floating-point number in C++

  • Steve Jessop
    Steve Jessop about 13 years
    The cplusplus documentation for atoi isn't excellent, it's incorrect. It fails to mention that if the numeric value of the string can't be represented in int, then the behaviour is undefined. It says instead that out-of-range values are clamped to INT_MAX/INT_MIN, which I can't find in either C++03 or C89. For untrusted/unverified input, or when dealing in bases that streams don't support, you need strtol, which has defined error behavior. And similar comments for atof/strtod.
  • Johannes Schaub - litb
    Johannes Schaub - litb about 13 years
    cplusplus.com is wrong about "atoi". It says about the return value "If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.", but the spec says that "If the value of the result cannot be represented, the behavior is undefined." and that "Except for the behavior on error, they are equivalent to (int)strtol(nptr, (char **)NULL, 10). The atoi[...] functions return the converted value.". cplusplus.com is known to be an incredible bad source of information for beginners.
  • Armen Tsirunyan
    Armen Tsirunyan about 13 years
    This is exactly what boost::lexical_cast does. And boost does it in a more generic fasion.
  • Viktor Sehr
    Viktor Sehr about 13 years
    True, I skimmed over the first answer and didnt see the boost::lexical_casts.
  • sbi
    sbi almost 13 years
    istr >> i1 >> f >> i2; badly misses a check for success.
  • Pubby
    Pubby almost 12 years
    Might want to add std::to_string
  • Abhineet
    Abhineet almost 12 years
    @ArmenTsirunyan: +10 from my end, One of the best answer i have ever seen that too in depth. Thanks for your answer.
  • Ferruccio
    Ferruccio over 11 years
    Actually boost::lexical_cast only uses stringstream for types that it doesn't know about. For types that it knows, lexical_cast always outperforms stringstreams (often by a pretty large margin). boost.org/doc/libs/1_50_0/doc/html/boost_lexical_cast/…
  • stefanct
    stefanct about 10 years
    One important point about boost::lexical_cast should be noted: its handling of int8_t and uint8_t which essentially are regarded as a char(!) leading to rather unpleasant surprises. details: boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast/…
  • fun4jimmy
    fun4jimmy over 9 years
    std::to_string loses a lot precision for floating point types. For instance double f = 23.4323897462387526; std::string f_str = std::to_string(f); returns a string of 23.432390. This makes it impossible to round trip floating point values using these functions.
  • KillianDS
    KillianDS over 9 years
    @fun4jimmy is this a restriction imposed by the standard or implementation specific? Will add it to the answer. Not that round-tripping floats through strings is a good idea ever.
  • fun4jimmy
    fun4jimmy over 9 years
    The C++ standard says "Returns: 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." I had a look at the C99 standard for printf and I think that the number of decimal places is dependent on #define DECIMAL_DIG in float.h.
  • fun4jimmy
    fun4jimmy over 9 years
    Bruce Dawson has some good articles on what precision is needed for round tripping floating point numbers on his blog.
  • Bruce Dawson
    Bruce Dawson over 9 years
    @KillianDS You say "an error is thrown." but that confuses me. Exceptions can be thrown, errors can be returned, so that phrase leaves me unclear about whether you are talking about exceptions or errors. Please clarify.
  • Bruce Dawson
    Bruce Dawson over 9 years
    @KillianDS There's nothing wrong with round-tripping floats and doubles through strings. You need a 17 digit mantissa for double and a nine-digit mantissa for float, and then you're golden. If to_string has no option to produce round-trippable variables then they are (IMHO) broken. Pity. fun4jimmy already added a link to my blog where I go over this in more detail.
  • KillianDS
    KillianDS over 9 years
    @BruceDawson Honestly I do not fully agree. It is not because it can be done with a long enough fractional part it's a good idea. to_string, printf and equals are intended for character representation (visuallization), not serialization. However I do agree that it's worth mentioning.
  • Bruce Dawson
    Bruce Dawson over 9 years
    @KillianDS I think it's fine for to_string to default to just displaying an approximation, but for it to not even have an option to uniquely identify the number seems terrible. These functions were an opportunity to fight back against years of confusion. Ah well.
  • Ident
    Ident over 8 years
    All these functions are affected by the global locale, which can lead to issues if you use libraries, and especially if using threads. See my question here: stackoverflow.com/questions/31977457/…
  • Massimo Costa
    Massimo Costa over 3 years
    HI, the answer is incomplete (no floating point converions) and also incorrect (to_string is not defined). Please be sure to priovide useful answers