web-dev-qa-db-fra.com

Comment puis-je convertir un std :: string en int?

Juste une petite question. J'ai pas mal regardé Internet et j'ai trouvé quelques solutions, mais aucune d'entre elles n'a encore fonctionné. Regarder convertir une chaîne en un entier et je ne veux pas dire des codes ASCII.

Pour un aperçu rapide, nous sommes passés dans une équation sous forme de chaîne. Nous devons le décomposer, le formater correctement et résoudre les équations linéaires. Maintenant, en disant cela, je ne suis pas capable de convertir une chaîne en un entier.

Je sais que la chaîne sera dans le format (-5) ou (25), etc., donc c'est certainement un int. Mais comment pouvons-nous extraire cela d'une chaîne?

Une façon dont je pensais était de lancer une boucle for/while à travers la chaîne, de rechercher un chiffre, d'extraire tous les chiffres suivants et ensuite de voir s'il y avait un '-' en tête, s'il y en a un, multipliez l'int 1.

Cela semble un peu compliqué pour un si petit problème. Des idées?

380
Brandon

En C++ 11, il existe quelques nouvelles fonctions de conversion de Nice de std::string vers un type de nombre.

Donc au lieu de

atoi( str.c_str() )

vous pouvez utiliser

std::stoi( str )

str est votre numéro en tant que std::string.

Il existe des versions pour tous les types de nombres: long stol(string), float stof(string), double stod(string), ... voir http://fr.cppreference.com/w/cpp/string/basic_string/stol

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

Pour être tout à fait correct, vérifiez les indicateurs d'erreur.

56
Winston Ewert

utilisez la fonction atoi pour convertir la chaîne en entier:

string a = "25";

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

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

35
brenjt

Les options possibles sont décrites ci-dessous:

1. Première option: 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

Ceci est une erreur (également montrée par cppcheck) car "scanf sans limites de largeur de champ peut planter avec des données d'entrée énormes sur certaines versions de libc" _ (voir ici et ici ) .

2. Deuxième option: std :: sto * ()

    #include <iostream>
    #include <string>

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

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

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

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

Cette solution est courte et élégante, mais elle n’est disponible que sur les compilateurs conformes C++ 11.

3. Troisième option: 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 ??

Cependant, avec cette solution, il est difficile de faire la distinction entre une entrée incorrecte (voir ici ).

4. Quatrième option: lexical_cast de Boost

    #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
        }

Cependant, il ne s’agit que d’une enveloppe de sstream, et la documentation suggère d’utiliser sstrem pour une meilleure gestion des erreurs (voir ici ).

5. Cinquième option: strto * ()

Cette solution est très longue, en raison de la gestion des erreurs, et est décrite ici. Puisqu'aucune fonction ne retourne un int simple, une conversion est nécessaire en cas de nombre entier (voir ici pour savoir comment cette conversion peut être réalisée).

6. Sixième option: 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

En résumé, la meilleure solution est C++ 11 std :: stoi () ou, en deuxième option, l’utilisation des bibliothèques Qt . Toutes les autres solutions sont déconseillées ou erronées.

27
Claudio

Qu'en est-il Boost.Lexical_cast ?

Voici leur exemple:

L'exemple suivant traite les arguments de ligne de commande comme une séquence de données numériques:

int main(int argc, char * argv[])
{
    using boost::lexical_cast;
    using boost::bad_lexical_cast;

    std::vector<short> args;

    while(*++argv)
    {
        try
        {
            args.Push_back(lexical_cast<short>(*argv));
        }
        catch(bad_lexical_cast &)
        {
            args.Push_back(0);
        }
    }
    ...
}
9
Robᵩ

Certes, ma solution ne fonctionnerait pas pour les entiers négatifs, mais elle extrairait tous les entiers positifs du texte d'entrée contenant des entiers. Il utilise numeric_only locale:

int main() {
        int num;
        std::cin.imbue(std::locale(std::locale(), new numeric_only()));
        while ( std::cin >> num)
             std::cout << num << std::endl;
        return 0;
}

Texte de saisie:

 the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878

Entiers de sortie:

 5
25
7987
78
9878

La classe numeric_only est définie comme suit:

struct numeric_only: std::ctype<char> 
{
    numeric_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
        return &rc[0];
    }
};

Démo en ligne complète: http://ideone.com/dRWSj

5
Nawaz

C'est probablement un peu exagéré, mais boost::lexical_cast<int>( theString ) devrait faire l'affaire Très bien. 

4
James Kanze

Sous Windows, vous pouvez utiliser:

const std::wstring hex = L"0x13";
const std::wstring dec = L"19";

int ret;
if (StrToIntEx(hex.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}
if (StrToIntEx(dec.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}

strtol, stringstream besoin de spécifier la base si vous avez besoin d'interpréter hexdécimal.

1
Jichao

atoi est une fonction intégrée qui convertit une chaîne en entier, en supposant que la chaîne commence par une représentation entière.

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

1
Eric

Mon code:

#include <iostream>
using namespace std;

int main()
{
    string s="32";  //String
    int n=stoi(s);  //Convert to int
    cout << n + 1 << endl;

    return 0;
}
1
Gonçalo Garrido

Eh bien, beaucoup de réponses, beaucoup de possibilités. Ce qui me manque ici, c'est une méthode universelle qui convertit une chaîne en différents types d'intégraux C++ (short, int, long, bool, ...) . J'ai proposé la solution suivante:

#include<sstream>
#include<exception>
#include<string>
#include<type_traits>

using namespace std;

template<typename T>
T toIntegralType(const string &str) {
    static_assert(is_integral<T>::value, "Integral type required.");
    T ret;
    stringstream ss(str);
    ss >> ret;
    if ( to_string(ret) != str)
        throw invalid_argument("Can't convert " + str);
    return ret;
}

Voici des exemples d'utilisation:

string str = "123";
int x = toIntegralType<int>(str); // x = 123

str = "123a";
x = toIntegralType<int>(str); // throws exception, because "123a" is not int

str = "1";
bool y = toIntegralType<bool>(str); // y is true
str = "0";
y = toIntegralType<bool>(str); // y is false
str = "00";
y = toIntegralType<bool>(str); // throws exception

Pourquoi ne pas simplement utiliser l'opérateur de sortie stringstream pour convertir une chaîne en un type intégral? Voici la réponse: Supposons qu'une chaîne contienne une valeur dépassant la limite du type intégral prévu. Par exemple, sous Wndows 64, int max est 2147483647 . Attribuons à une chaîne une valeur max int + 1: string str = "2147483648". Maintenant, lors de la conversion de la chaîne en un entier:

stringstream ss(str);
int x;
ss >> x;

x devient 2147483647, ce qui est définitivement une erreur: la chaîne "2147483648" n'était pas censée être convertie en int 2147483647. La fonction fournie toIntegralType détecte ces erreurs et lève une exception.

0

De http://www.cplusplus.com/reference/string/stoi/

// stoi example
#include <iostream>   // std::cout
#include <string>     // std::string, std::stoi

int main ()
{
  std::string str_dec = "2001, A Space Odyssey";
  std::string str_hex = "40c3";
  std::string str_bin = "-10010110001";
  std::string str_auto = "0x7f";

  std::string::size_type sz;   // alias of size_t

  int i_dec = std::stoi (str_dec,&sz);
  int i_hex = std::stoi (str_hex,nullptr,16);
  int i_bin = std::stoi (str_bin,nullptr,2);
  int i_auto = std::stoi (str_auto,nullptr,0);

  std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n";
  std::cout << str_hex << ": " << i_hex << '\n';
  std::cout << str_bin << ": " << i_bin << '\n';
  std::cout << str_auto << ": " << i_auto << '\n';

  return 0;
}

Sortie:

2001, une odyssée de l'espace: 2001 et [ une odyssée de l'espace]

40c3: 16579

-10010110001: -1201

0x7f: 127

0
user7967189
ll toll(string a){
    ll ret=0;
    bool minus=false;
    for(auto i:a){
        if(i=='-'){ minus=true; continue; }
        ret*=10;
        ret+=(i-'0');
    } if(minus) ret*=-1;
    return ret;
    # ll is defined as, #define ll long long int
    # usage: ll a = toll(string("-1234"));
}
0
Amey Kudari

Version à une ligne: long n = strtol(s.c_str(), NULL, base);

(s est la chaîne, et base est une int telle que 2, 8, 10, 16.)

Vous pouvez vous référer à ce lien pour plus de détails sur strtol.


L'idée principale est d'utiliser strtol function, qui est inclus dans cstdlib.

Puisque strtol traite uniquement avec le tableau char, nous devons convertir string en tableau char. Vous pouvez vous référer à ce lien .

Un exemple:

#include <iostream>
#include <string>   // string type
#include <bitset>   // bitset type used in the output

int main(){
    s = "1111000001011010";
    long t = strtol(s.c_str(), NULL, 2); // 2 is the base which parse the string

    cout << s << endl;
    cout << t << endl;
    cout << hex << t << endl;
    cout << bitset<16> (t) << endl;

    return 0;
}

qui produira:

1111000001011010
61530
f05a
1111000001011010
0
Hansimov