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?

Brandon
quelle
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

tgmath
quelle
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.

Winston Ewert
quelle
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.

Claudio
quelle
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
40

Verwenden Sie die Funktion atoi, um die Zeichenfolge in eine Ganzzahl zu konvertieren:

string a = "25";

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

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

brenjt
quelle
14
Niemals benutzen atoi. strtolmacht alles atoimacht, aber besser und scheitert sicher.
Ben Voigt
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);
        }
    }
    ...
}
Robᵩ
quelle
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

Nawaz
quelle
4

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

James Kanze
quelle
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

atoi ist eine integrierte Funktion, die eine Zeichenfolge in eine Ganzzahl konvertiert, vorausgesetzt, die Zeichenfolge beginnt mit einer Ganzzahldarstellung.

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

Eric
quelle
atoiVerwenden Sie strtolstattdessen jedes Mal, wenn Sie darüber nachdenken .
Ben Voigt
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.

Jichao
quelle
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.

Andrushenko Alexander
quelle
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

user7967189
quelle
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;
}
Gonçalo Garrido
quelle
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"));
}
Amey Kudari
quelle
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 ++

Bala Singh
quelle
-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
Hansimov
quelle
-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

Anfänger
quelle
1
Die Frage ist eher die Konvertierung von stringnach intals von von charnach string.
Yuchen Zhong
Buggy und nicht passend zur Frage
Caoanan