How can I convert a std::string to int?

1,773,568

Solution 1

In C++11 there are some nice new convert functions from std::string to a number type.

So instead of

atoi( str.c_str() )

you can use

std::stoi( str )

where str is your number as std::string.

There are version for all flavours of numbers: long stol(string), float stof(string), double stod(string),... see http://en.cppreference.com/w/cpp/string/basic_string/stol

Solution 2

The possible options are described below:

1. sscanf()

    #include <cstdio>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        if(sscanf(str.c_str(), "%d", &i) != 1)
            // error management

        // string -> float
        if(sscanf(str.c_str(), "%f", &f) != 1)
            // error management
    
        // string -> double 
        if(sscanf(str.c_str(), "%lf", &d) != 1)
            // error management

This is an error (also shown by cppcheck) because "scanf without field width limits can crash with huge input data on some versions of libc" (see here, and here).

2. std::sto()*

    #include <iostream>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        try {
            // string -> integer
            int i = std::stoi(str);

            // string -> float
            float f = std::stof(str);

            // string -> double 
            double d = std::stod(str);
        } catch (...) {
            // error management
        }   

This solution is short and elegant, but it is available only on on C++11 compliant compilers.

3. sstreams

    #include <string>
    #include <sstream>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        std::istringstream ( str ) >> i;

        // string -> float
        std::istringstream ( str ) >> f;

        // string -> double 
        std::istringstream ( str ) >> d;

        // error management ??

However, with this solution is hard to distinguish between bad input (see here).

4. Boost's lexical_cast

    #include <boost/lexical_cast.hpp>
    #include <string>

        std::string str;

        try {
            int i = boost::lexical_cast<int>( str.c_str());
            float f = boost::lexical_cast<int>( str.c_str());
            double d = boost::lexical_cast<int>( str.c_str());
            } catch( boost::bad_lexical_cast const& ) {
                // Error management
        }

However, this is just a wrapper of sstream, and the documentation suggests to use sstream for better error management (see here).

5. strto()*

This solution is very long, due to error management, and it is described here. Since no function returns a plain int, a conversion is needed in case of integer (see here for how this conversion can be achieved).

6. Qt

    #include <QString>
    #include <string>

        bool ok;
        std::string;

        int i = QString::fromStdString(str).toInt(&ok);
        if (!ok)
            // Error management
    
        float f = QString::fromStdString(str).toFloat(&ok);
        if (!ok)
            // Error management 

        double d = QString::fromStdString(str).toDouble(&ok);
        if (!ok)
    // Error management     
    

Conclusions

Summing up, the best solution is C++11 std::stoi() or, as a second option, the use of Qt libraries. All other solutions are discouraged or buggy.

Solution 3

std::istringstream ss(thestring);
ss >> thevalue;

To be fully correct you'll want to check the error flags.

Solution 4

use the atoi function to convert the string to an integer:

string a = "25";

int b = atoi(a.c_str());

http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

Solution 5

To be more exhaustive (and as it has been requested in comments), I add the solution given by C++17 using std::from_chars.

std::string str = "10";
int number;
std::from_chars(str.data(), str.data()+str.size(), number);

If you want to check whether the conversion was successful:

std::string str = "10";
int number;
auto [ptr, ec] = std::from_chars(str.data(), str.data()+str.size(), number);
assert(ec == std::errc{});
// ptr points to chars after read number

Moreover, to compare the performance of all these solutions, see the following quick-bench link: https://quick-bench.com/q/GBzK53Gc-YSWpEA9XskSZLU963Y

(std::from_chars is the fastest and std::istringstream is the slowest)

Share:
1,773,568
Brandon
Author by

Brandon

Updated on February 15, 2022

Comments

  • Brandon
    Brandon about 2 years

    I want to convert a string to an int and I don't mean ASCII codes.

    For a quick run-down, we are passed in an equation as a string. We are to break it down, format it correctly and solve the linear equations. Now, in saying that, I'm not able to convert a string to an int.

    I know that the string will be in either the format (-5) or (25) etc. so it's definitely an int. But how do we extract that from a string?

    One way I was thinking is running a for/while loop through the string, check for a digit, extract all the digits after that and then look to see if there was a leading '-', if there is, multiply the int by -1.

    It seems a bit over complicated for such a small problem though. Any ideas?

  • Nawaz
    Nawaz over 12 years
    This will not extract -5 from (-5).
  • Winston Ewert
    Winston Ewert over 12 years
    @Nawaz, are the parens actually there, or is that just how the OP is presenting his strings?
  • Nawaz
    Nawaz over 12 years
    I don't know. I'm just pointing out the limitation of the approach.
  • Winston Ewert
    Winston Ewert over 12 years
    @Nawaz, that's not really a limitation, more of preprocessing required to get rid of parens.
  • Nawaz
    Nawaz over 12 years
    That is what is called limitation. It cannot directly operate on input.
  • James Kanze
    James Kanze over 12 years
    A typo. It should be simply boost::lexical_cast<int>( theString ) (where theString is the name of the variable which contains the string you want to convert to int).
  • Winston Ewert
    Winston Ewert over 12 years
    @Nawaz, It also can't operate on the input "WERWER". I don't think the parens are actually part of his actual string and I don't think the fact that I don't parse them is relevant.
  • Nawaz
    Nawaz over 12 years
    I said that because he used the word "extract" when he asked : But how do we extract that from a string?
  • Winston Ewert
    Winston Ewert over 12 years
    @Nawaz, ok... I don't take the word that way but I see how you could.
  • Yuchen
    Yuchen almost 10 years
    The question is about converting from string to int rather than from char to string.
  • Ben Voigt
    Ben Voigt about 9 years
    Never ever use atoi. strtol does everything atoi does, but better, and fails safely.
  • Ben Voigt
    Ben Voigt about 9 years
    Any time you think about atoi, use strtol instead.
  • CC.
    CC. almost 9 years
    For issues with std::stoi see stackoverflow.com/a/6154614/195527 : it will convert "11x" to integer 11.
  • Yuchen
    Yuchen about 8 years
    The link is broken. Could you fix it?
  • Ulad Kasach
    Ulad Kasach about 8 years
    #include <stdlib.h> /* atoi */
  • Tin Wizard
    Tin Wizard almost 8 years
    @CC That's also the behavior of atoi: cplusplus.com/reference/cstdlib/atoi "The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function."
  • caoanan
    caoanan about 7 years
    buggy and not matching the question
  • Claudio
    Claudio almost 7 years
    Fixed. Thanks for reporting.
  • luca
    luca almost 6 years
    Beautiful summary, many thanks. May I suggest to add an initial comment suggesting the final solution so that only people interested in the details keep reading?
  • NathanOliver
    NathanOliver almost 5 years
    Would you mind updating this answer with from_chars from C++17? It is supposed to be orders of magnitude faster than stoi.
  • xception
    xception over 4 years
    this should be the accepted answer, also you forgot (or rather should add cause it's an old answer) from_chars
  • phuclv
    phuclv over 4 years
    stoi should be preferred. See Why shouldn't I use atoi()?
  • Arne
    Arne about 4 years
    Any idea why there is std::stoi and std::stoul, but no std::stou or std::stoui to convert a string to unsigned int? Only to unsigned long?
  • HolyBlackCat
    HolyBlackCat over 3 years
    This doesn't handle overflows or negative numbers. The second function is very similar to atoi, not sure why write it by hand. Also, some things could be improved: don't pass strings by value, use standard functions more (the first function could be rewritten using something like std::all_of + std::isdigit).
  • Jackt
    Jackt almost 3 years
    if returns zeo ??? you dont know if the string was actually 0 or conversion error !
  • Marc Dirven
    Marc Dirven almost 3 years
    Don't use sscanf. It's a C API function, and the question is regarding C++. If you're planning to use sscanf then at least use std::.
  • cigien
    cigien over 2 years
    std::stoi is already mentioned in multiple other answers, and the question is not asking about converting double to string.
  • Admin
    Admin over 2 years
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
  • Vainstein K
    Vainstein K over 2 years
    Expanding on @BenVoigt's comment: a big reason to avoid atoi is that it reports conversion failure solely by returning 0! atoi not so much fails unsafely as it fails silently.
  • Ben Voigt
    Ben Voigt over 2 years
    @VainsteinK: Some failures are reported by returning 0. Others cause undefined behavior with atoi. That makes it useless for validation of untrusted input. wiki.sei.cmu.edu/confluence/display/c/…
  • Yongqi Z
    Yongqi Z over 2 years
    But what will you do if std::stoi("not-a-num"), this will case core dumped