Wie kann ich einen std :: string in int konvertieren?


484

Habe nur eine kurze Frage. Ich habe mich ziemlich viel im Internet umgesehen und ein paar Lösungen gefunden, aber keine davon hat bisher funktioniert. Wenn ich eine Zeichenfolge in eine int konvertiere, meine ich nicht ASCII-Codes.

Für einen schnellen Ablauf werden wir in einer Gleichung als Zeichenfolge übergeben. Wir sollen es zerlegen, richtig formatieren und die linearen Gleichungen lösen. Wenn ich das sage, kann ich einen String nicht in einen Int konvertieren.

Ich weiß, dass die Zeichenfolge entweder das Format (-5) oder (25) usw. hat, also ist es definitiv ein int. Aber wie extrahieren wir das aus einer Zeichenfolge?

Eine Möglichkeit, die ich mir vorgestellt habe, besteht darin, eine for / while-Schleife durch die Zeichenfolge zu führen, nach einer Ziffer zu suchen, danach alle Ziffern zu extrahieren und dann zu prüfen, ob ein führendes '-' vorhanden ist. Wenn dies der Fall ist, multiplizieren Sie das int mit - 1.

Für ein so kleines Problem scheint es allerdings etwas zu kompliziert. Irgendwelche Ideen?


9
Hast du es versucht atoi()?
i_am_jorf



7
@Chad Sie empfehlen also, eine ganze Bibliothek für etwas zu verwenden, das die Sprache sowieso mit Standardbibliotheken tun kann?
Bojangles

6
@Brandon, wenn Sie eine std::string myStringhaben und verwenden möchten atoi, dann möchten Sie sagen atoi(myString.c_str()).
Robᵩ

Antworten:


726

In C ++ 11 gibt es einige nette neue Konvertierungsfunktionen von std::stringin einen Zahlentyp.

Also statt

atoi( str.c_str() )

Sie können verwenden

std::stoi( str )

wo strist deine nummer als std::string.

Es gibt Version für alle Varianten von Zahlen: long stol(string), float stof(string), double stod(string), ... siehe http://en.cppreference.com/w/cpp/string/basic_string/stol


5
Bei Problemen mit std :: stoi siehe stackoverflow.com/a/6154614/195527 : Es wird "11x"in eine Ganzzahl konvertiert 11.
CC.

5
#include <stdlib.h> / * atoi * /
Ulad Kasach

4
@CC Das ist auch das Verhalten von atoi: cplusplus.com/reference/cstdlib/atoi "Die Zeichenfolge kann zusätzliche Zeichen nach denen enthalten, die die Integralzahl bilden, die ignoriert werden und keinen Einfluss auf das Verhalten dieser Funktion haben."
Tin Wizard

4
Würde es Ihnen etwas ausmachen, diese Antwort mit from_charsC ++ 17 zu aktualisieren ? Es soll Größenordnungen schneller sein als stoi.
NathanOliver

stoisollte bevorzugt werden. Siehe Warum sollte ich atoi () nicht verwenden?
18.

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

Um vollständig korrekt zu sein, sollten Sie die Fehlerflags überprüfen.


2
Dies wird nicht extrahiert -5aus (-5).
Nawaz

@Nawaz, sind die Eltern tatsächlich da oder präsentiert der OP so seine Saiten?
Winston Ewert

Ich weiß es nicht. Ich weise nur auf die Einschränkung des Ansatzes hin.
Nawaz

16
@Nawaz, es kann auch nicht am Eingang "WERWER" arbeiten. Ich denke nicht, dass die Parens tatsächlich Teil seiner eigentlichen Zeichenfolge sind, und ich denke nicht, dass die Tatsache, dass ich sie nicht analysiere, relevant ist.
Winston Ewert

4
@Nawaz, ok ... Ich verstehe das Wort nicht so, aber ich sehe, wie du es könntest.
Winston Ewert

44

Die möglichen Optionen werden unten beschrieben:

1. Erste 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

Dies ist ein Fehler (auch durch cppcheck angezeigt), da "scanf ohne Feldbreitenbeschränkungen bei einigen libc-Versionen mit großen Eingabedaten abstürzen kann" (siehe hier und hier ).

2. Zweite Option: 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
        }   

Diese Lösung ist kurz und elegant, aber nur auf C ++ 11-kompatiblen Compilern verfügbar.

3. Dritte 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 ??

Bei dieser Lösung ist es jedoch schwierig, zwischen schlechten Eingaben zu unterscheiden (siehe hier ).

4. Vierte Option: Boosts 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
        }

Dies ist jedoch nur ein Wrapper von sstream, und in der Dokumentation wird empfohlen, ihn sstreamfür ein besseres Fehlermanagement zu verwenden (siehe hier ).

5. Fünfte Option: strto * ()

Diese Lösung ist aufgrund des Fehlermanagements sehr lang und wird hier beschrieben. Da keine Funktion ein einfaches int zurückgibt, ist bei einer Ganzzahl eine Konvertierung erforderlich (siehe hier, wie diese Konvertierung erreicht werden kann).

6. Sechste 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     

Schlussfolgerungen

Zusammenfassend ist die beste Lösung C ++ 11 std::stoi()oder als zweite Option die Verwendung von Qt-Bibliotheken. Alle anderen Lösungen sind nicht empfehlenswert oder fehlerhaft.


Fest. Vielen Dank für die Berichterstattung.
Claudio

Schöne Zusammenfassung, vielen Dank. Darf ich vorschlagen, einen ersten Kommentar hinzuzufügen, der die endgültige Lösung vorschlägt, damit nur Personen, die an den Details interessiert sind, weiterlesen?
Luca

1
Dies sollte die akzeptierte Antwort sein, auch Sie haben vergessen (oder besser gesagt, weil es eine alte Antwort ist) from_chars
xception


9

Was ist mit Boost.Lexical_cast ?

Hier ist ihr Beispiel:

Im folgenden Beispiel werden Befehlszeilenargumente als Folge numerischer Daten behandelt:

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);
        }
    }
    ...
}

Die Verbindung ist unterbrochen. Könnten Sie es beheben?
Yuchen Zhong

5

Zugegeben, meine Lösung würde für negative Ganzzahlen nicht funktionieren, aber sie extrahiert alle positiven Ganzzahlen aus Eingabetext, der Ganzzahlen enthält. Es verwendet das numeric_onlyGebietsschema:

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

Eingabetext:

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

Ausgabe-Ganzzahlen:

 5
25
7987
78
9878

Die Klasse numeric_onlyist definiert als:

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];
    }
};

Vollständige Online-Demo: http://ideone.com/dRWSj


4

Es ist wahrscheinlich ein bisschen übertrieben, boost::lexical_cast<int>( theString )sollte aber ganz gut zum Job passen.


Ein Tippfehler. Es sollte einfach sein boost::lexical_cast<int>( theString )(wo theStringist der Name der Variablen, die die Zeichenfolge enthält, in die Sie konvertieren möchten int).
James Kanze


1

In Windows können Sie Folgendes verwenden:

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, stringstreammüssen die Basis angeben, wenn Sie hexadezimal interpretieren müssen.


1

Nun, viele Antworten, viele Möglichkeiten. Was mir hier fehlt, ist eine universelle Methode, die einen String in verschiedene C ++ - Integraltypen konvertiert (kurz, int, lang, bool, ...). Ich habe folgende Lösung gefunden:

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

Hier sind Anwendungsbeispiele:

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

Warum nicht einfach den Stringstream-Ausgabeoperator verwenden, um einen String in einen integralen Typ zu konvertieren? Hier ist die Antwort: Angenommen, eine Zeichenfolge enthält einen Wert, der die Grenze für den beabsichtigten Integraltyp überschreitet. Zum Beispiel ist auf Windows 64 max int 2147483647. Weisen wir einem String einen Wert max int + 1 zu: string str = "2147483648". Wenn Sie nun den String in ein int konvertieren:

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

x wird zu 2147483647, was definitiv ein Fehler ist: Die Zeichenfolge "2147483648" sollte nicht in die int 2147483647 konvertiert werden. Die bereitgestellte Funktion toIntegralType erkennt solche Fehler und löst eine Ausnahme aus.


0

Von 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;
}

Ausgabe:

2001, Eine Weltraum-Odyssee: 2001 und [, Eine Weltraum-Odyssee]

40c3: 16579

-10010110001: -1201

0x7f: 127


0

Mein 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;
}

0
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

Um von der Zeichenfolgendarstellung in einen ganzzahligen Wert zu konvertieren, können wir std :: stringstream verwenden.

Wenn der konvertierte Wert für den Datentyp "Integer" außerhalb des Bereichs liegt, wird INT_MIN oder INT_MAX zurückgegeben.

Auch wenn der Zeichenfolgenwert nicht als gültiger int-Datentyp dargestellt werden kann, wird 0 zurückgegeben.

#include 
#include 
#include 

int main() {

    std::string x = "50";
    int y;
    std::istringstream(x) >> y;
    std::cout << y << '\n';
    return 0;
}

Ausgabe: 50

Gemäß der obigen Ausgabe können wir sehen, dass es von Zeichenfolgenummern in Ganzzahlen konvertiert wird.

Quelle und mehr unter Zeichenfolge zu int c ++


-2

Einzeilige Version : long n = strtol(s.c_str(), NULL, base);.

( sist die Zeichenfolge und baseist eine intwie 2, 8, 10, 16.)

Sie können auf diesen Link für weitere Details von verweisen strtol.


Die Kernidee ist die Verwendung der strtolFunktion, die in enthalten ist cstdlib.

Da strtolnur mit charArray behandelt wird, müssen wir stringin charArray konvertieren . Sie können auf diesen Link verweisen .

Ein Beispiel:

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

welches ausgegeben wird:

1111000001011010
61530
f05a
1111000001011010

-3

Es gibt noch einen anderen einfachen Weg: Angenommen, Sie haben einen Charakter wie diesen, c='4'daher können Sie einen der folgenden Schritte ausführen:

1. int q

q=(int) c ; (q is now 52 in ascii table ) . q=q-48; remember that adding 48 to digits is their ascii code .

der zweite Weg:

q=c-'0'; the same , character '0' means 48


1
Die Frage ist eher die Konvertierung von stringnach intals von von charnach string.
Yuchen Zhong

Buggy und nicht passend zur Frage
Caoanan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.