it-swarm.com.de

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

Hab einfach eine kurze Frage. Ich habe mich ein bisschen im Internet umgesehen und ein paar Lösungen gefunden, aber noch keine davon hat funktioniert. Beim Konvertieren einer Zeichenfolge in ein int und ich meine nicht ASCII - Codes.

Für einen schnellen Ablauf werden wir in einer Gleichung als String übergeben. Wir müssen es aufschlüsseln, richtig formatieren und die linearen Gleichungen lösen. Wenn ich das sage, kann ich eine Zeichenfolge nicht in eine int konvertieren.

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

Eine Möglichkeit, über die ich nachgedacht habe, ist, eine for/while-Schleife durch die Zeichenfolge zu führen, nach einer Ziffer zu suchen, alle Ziffern danach zu extrahieren und dann zu sehen, ob es ein führendes '-' gab, falls vorhanden, das int mit multiplizieren. 1.

Für ein so kleines Problem erscheint es jedoch etwas kompliziert. Irgendwelche Ideen?

380
Brandon

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

Also statt 

atoi( str.c_str() )

sie können verwenden

std::stoi( str )

dabei ist str Ihre Nummer als std::string.

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

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

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

56
Winston Ewert

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/

35
brenjt

Die möglichen Optionen werden nachfolgend 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 (wird auch von cppcheck angezeigt), da "scanf ohne Feldbreitenbegrenzungen kann bei einigen libc-Versionen mit großen Eingabedaten abstürzen" (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(s);

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

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

Diese Lösung ist kurz und elegant, sie ist jedoch nur auf C++ 11-Compliants-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 fehlerhaften Eingaben zu unterscheiden (siehe hier ).

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

Dies ist jedoch nur ein Wrapper von sstream, und die Dokumentation schlägt vor, sstrem für ein besseres Fehlermanagement zu verwenden (siehe hier ).

5. Fünfte Option: strto * ()

Diese Lösung ist aufgrund der Fehlerverwaltung sehr lang und wird hier beschrieben. Da keine Funktion ein einfaches int zurückgibt, ist bei Integer 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 entmutigt oder fehlerhaft.

27
Claudio

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

Zugegeben, meine Lösung würde nicht für negative Ganzzahlen funktionieren, aber sie extrahiert alle positiven Ganzzahlen aus Eingabetext, der Ganzzahlen enthält. Es verwendet 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;
}

Eingabetext:

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

Ausgabezahlen:

 5
25
7987
78
9878

Die Klasse numeric_only ist 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

5
Nawaz

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

4
James Kanze

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, stringstream muss die Basis angeben, wenn Sie Hexdecimal interpretieren müssen.

1
Jichao

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

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

1
Eric

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

Nun, viele Antworten, viele Möglichkeiten. Was mir fehlt, ist eine universelle Methode, die eine Zeichenfolge in verschiedene C++ - Integraltypen konvertiert (short, int, long, bool, ...) ... und 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 Beispiele für die Verwendung:

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 eine Zeichenfolge in einen Integraltyp 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 Wndows 64 max int 2147483647 . Ordnen 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 das int 2147483647 konvertiert werden. Die bereitgestellte Funktion toIntegralType erkennt solche Fehler und löst eine Ausnahme aus.

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

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

(s ist die Zeichenfolge und base ist eine int, z. B. 2, 8, 10, 16.)

Unter diesem Link finden Sie weitere Details zu strtol.


Die Grundidee ist die Verwendung von strtol function, die in cstdlib enthalten ist.

Da strtol nur mit char-Array verarbeitet, müssen wir string in char-Array 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;
}

welche ausgegeben werden:

1111000001011010
61530
f05a
1111000001011010
0
Hansimov