So konvertieren Sie eine Zahl in einen String und umgekehrt in C ++

120

Da diese Frage jede Woche gestellt wird, kann diese FAQ vielen Benutzern helfen.

  • So konvertieren Sie eine Ganzzahl in eine Zeichenfolge in C ++

  • So konvertieren Sie eine Zeichenfolge in C ++ in eine Ganzzahl

  • So konvertieren Sie eine Gleitkommazahl in eine Zeichenfolge in C ++

  • So konvertieren Sie eine Zeichenfolge in C ++ in eine Gleitkommazahl

Armen Tsirunyan
quelle
Für eine solche
Firzok Nadeem

Antworten:

129

Update für C ++ 11

Da der C++11Standard - String-to-Zahl - Umwandlung und umgekehrt sind in in der Standardbibliothek eingebaut. Alle folgenden Funktionen sind in <string>(gemäß Absatz 21.5) vorhanden.

Zeichenfolge zu numerisch

float              stof(const string& str, size_t *idx = 0);
double             stod(const string& str, size_t *idx = 0);
long double        stold(const string& str, size_t *idx = 0);
int                stoi(const string& str, size_t *idx = 0, int base = 10);
long               stol(const string& str, size_t *idx = 0, int base = 10);
unsigned long      stoul(const string& str, size_t *idx = 0, int base = 10);
long long          stoll(const string& str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);

Jeder von diesen nimmt eine Zeichenfolge als Eingabe und versucht, sie in eine Zahl umzuwandeln. Wenn keine gültige Nummer erstellt werden konnte, z. B. weil keine numerischen Daten vorhanden sind oder die Nummer außerhalb des Bereichs für den Typ liegt, wird eine Ausnahme ausgelöst ( std::invalid_argumentoder std::out_of_range).

Wenn die Konvertierung erfolgreich war und idxnicht 0, idxenthält sie den Index des ersten Zeichens, das nicht zum Decodieren verwendet wurde. Dies könnte ein Index hinter dem letzten Zeichen sein.

Schließlich ermöglichen die Integraltypen die Angabe einer Basis. Für Ziffern größer als 9 wird das Alphabet angenommen ( a=10bis z=35). Weitere Informationen zur genauen Formatierung, die für Gleitkommazahlen , vorzeichenbehaftete Ganzzahlen und vorzeichenlose Ganzzahlen analysiert werden kann, finden Sie hier .

Schließlich gibt es für jede Funktion auch eine Überladung, die a std::wstringals ersten Parameter akzeptiert .

numerisch zu string

string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long long val);
string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);

Diese sind einfacher, Sie übergeben den entsprechenden numerischen Typ und erhalten eine Zeichenfolge zurück. Für Formatierungsoptionen sollten Sie zur Stringsream-Option C ++ 03 zurückkehren und Stream-Manipulatoren verwenden, wie in einer anderen Antwort hier erläutert.

Wie in den Kommentaren erwähnt, greifen diese Funktionen auf eine Standard-Mantissengenauigkeit zurück, die wahrscheinlich nicht die maximale Genauigkeit ist. Wenn für Ihre Anwendung mehr Präzision erforderlich ist, kehren Sie am besten zu anderen Formatierungsverfahren für Zeichenfolgen zurück.

Es sind auch ähnliche Funktionen definiert, die benannt to_wstringsind. Diese geben a zurück std::wstring.

KillianDS
quelle
3
std::to_stringverliert viel Präzision für Gleitkommatypen. double f = 23.4323897462387526; std::string f_str = std::to_string(f);Gibt beispielsweise eine Zeichenfolge von 23.432390 zurück. Dies macht es unmöglich, Gleitkommawerte mit diesen Funktionen zu umrunden.
fun4jimmy
@ fun4jimmy ist dies eine Einschränkung, die durch den Standard oder die Implementierung spezifisch ist? Fügt es der Antwort hinzu. Nicht dass Roundtripping durch Saiten schwebt, ist jemals eine gute Idee.
KillianDS
Der C ++ - Standard lautet " Rückgabe: Jede Funktion gibt ein Zeichenfolgenobjekt zurück, das die Zeichendarstellung des Werts ihres Arguments enthält, das durch Aufrufen sprintf(buf, fmt, val)mit einem Formatbezeichner von "% d " , "% u " , "% ld " , " generiert würde. " % lu " "% LLD" , "% LLU" , "% f" , "% f" oder "% Lf" jeweils gegebenes bufbezeichnet einen internen Zeichenpuffer mit ausreichender Größe. "Ich habe mir den C99- Standard für printf angesehen und denke, dass die Anzahl der Dezimalstellen von #define DECIMAL_DIGin abhängtfloat.h .
fun4jimmy
Bruce Dawson hat in seinem Blog einige gute Artikel darüber veröffentlicht, welche Präzision für das Auslösen von Gleitkommazahlen erforderlich ist .
fun4jimmy
2
Alle diese Funktionen sind vom globalen Gebietsschema betroffen, was bei Verwendung von Bibliotheken und insbesondere bei Verwendung von Threads zu Problemen führen kann. Siehe meine Frage hier: stackoverflow.com/questions/31977457/…
Ident
86

So konvertieren Sie eine Zahl in eine Zeichenfolge in C ++ 03

  1. Verwenden Sie dieFunktionenitoaoder nichtitof, da sie nicht dem Standard entsprechen und daher nicht tragbar sind.
  2. Verwenden Sie String-Streams

     #include <sstream>  //include this to use string streams
     #include <string> 
    
    int main()
    {    
        int number = 1234;
    
        std::ostringstream ostr; //output string stream
        ostr << number; //use the string stream just like cout,
        //except the stream prints not to stdout but to a string.
    
        std::string theNumberString = ostr.str(); //the str() function of the stream 
        //returns the string.
    
        //now  theNumberString is "1234"  
    }

    Beachten Sie, dass Sie Zeichenfolgenströme auch verwenden können, um Gleitkommazahlen in Zeichenfolgen umzuwandeln und die Zeichenfolge wie bei zu formatieren cout

    std::ostringstream ostr;
    float f = 1.2;
    int i = 3;
    ostr << f << " + " i << " = " << f + i;   
    std::string s = ostr.str();
    //now s is "1.2 + 3 = 4.2" 

    Sie können Stream - Manipulatoren, wie verwenden std::endl, std::hexund Funktionen std::setw(), std::setprecision()auf genau die gleiche Art und Weise usw. mit String - Streams wie mitcout

    Nicht verwechseln std::ostringstream mitstd::ostrstream. Letzteres ist veraltet

  3. Verwenden Sie die lexikalische Besetzung . Wenn Sie mit Boost nicht vertraut sind, ist es eine gute Idee, mit einer kleinen Bibliothek wie diesem lexical_cast zu beginnen. Um Boost und seine Dokumentation herunterzuladen und zu installieren, klicken Sie hier . Obwohl Boost nicht im C ++ - Standard enthalten ist, werden viele Boost-Bibliotheken irgendwann standardisiert, und Boost wird allgemein als die beste C ++ - Bibliothek angesehen.

    Die lexikalische Besetzung verwendet darunter liegende Streams, daher ist diese Option im Grunde die gleiche wie die vorherige, nur weniger ausführlich.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       float f = 1.2;
       int i = 42;
       std::string sf = boost::lexical_cast<std::string>(f); //sf is "1.2"
       std::string si = boost::lexical_cast<std::string>(i); //sf is "42"
    }

So konvertieren Sie eine Zeichenfolge in C ++ 03 in eine Zahl

  1. Die leichteste Option, die von C geerbt wird, sind die Funktionen atoi(für Ganzzahlen (alphabetisch bis ganzzahlig)) und atof(für Gleitkommawerte (alphabetisch bis Gleitkomma)). Diese Funktionen nehmen einen C-String als Argument ( const char *) und damit ihre Nutzung kann ein nicht gerade gut C ++ Praxis berücksichtigt werden. cplusplus.com bietet eine leicht verständliche Dokumentation zu atoi und atof, einschließlich des Verhaltens bei schlechten Eingaben. Der Link enthält jedoch den Fehler, dass gemäß dem Standard das Verhalten undefiniert ist, wenn die Eingabenummer zu groß ist, um in den Zieltyp zu passen.

    #include <cstdlib> //the standard C library header
    #include <string>
    int main()
    {
        std::string si = "12";
        std::string sf = "1.2";
        int i = atoi(si.c_str()); //the c_str() function "converts" 
        double f = atof(sf.c_str()); //std::string to const char*
    }
  2. Verwenden Sie String-Streams (diesmal geben Sie einen String-Stream ein istringstream). Auch hier wird istringstream genauso verwendet cin. Auch hier nicht verwechseln istringstreammit istrstream. Letzteres ist veraltet.

    #include <sstream>
    #include <string>
    int main()
    {
       std::string inputString = "1234 12.3 44";
       std::istringstream istr(inputString);
       int i1, i2;
       float f;
       istr >> i1 >> f >> i2;
       //i1 is 1234, f is 12.3, i2 is 44  
    }
  3. Verwenden Sie die lexikalische Besetzung .

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       std::string sf = "42.2"; 
       std::string si = "42";
       float f = boost::lexical_cast<float>(sf); //f is 42.2
       int i = boost::lexical_cast<int>(si);  //i is 42
    }       

    Bei einer fehlerhaften Eingabe wird lexical_casteine Ausnahme vom Typ ausgelöstboost::bad_lexical_cast

Armen Tsirunyan
quelle
4
Die cplusplus-Dokumentation für atoiist nicht ausgezeichnet, sie ist falsch. Es wird nicht erwähnt, dass intdas Verhalten undefiniert ist , wenn der numerische Wert der Zeichenfolge nicht dargestellt werden kann . Es heißt stattdessen, dass Werte außerhalb des Bereichs an INT_MAX/ geklemmt werden INT_MIN, was ich weder in C ++ 03 noch in C89 finde. Für nicht vertrauenswürdige / nicht verifizierte Eingaben oder wenn es sich um Basen handelt, die Streams nicht unterstützen, benötigen Sie ein strtoldefiniertes Fehlerverhalten. Und ähnliche Kommentare für atof/ strtod.
Steve Jessop
2
cplusplus.com ist falsch in Bezug auf "atoi". Über den Rückgabewert steht "Wenn keine gültige Konvertierung durchgeführt werden konnte, wird ein Nullwert zurückgegeben. Wenn der korrekte Wert außerhalb des Bereichs der darstellbaren Werte liegt, wird INT_MAX oder INT_MIN zurückgegeben.", Aber die Spezifikation besagt, dass "If the Der Wert des Ergebnisses kann nicht dargestellt werden, das Verhalten ist nicht definiert. " und dass "Mit Ausnahme des Verhaltens bei Fehlern sind sie äquivalent zu (int)strtol(nptr, (char **)NULL, 10). Die atoi [...] Funktionen geben den konvertierten Wert zurück." cplusplus.com ist bekanntermaßen eine unglaublich schlechte Informationsquelle für Anfänger.
Johannes Schaub - litb
istr >> i1 >> f >> i2;verfehlt dringend einen Scheck für den Erfolg.
sbi
4
std::to_string
Vielleicht
1
@ArmenTsirunyan: +10 von meinem Ende, eine der besten Antworten, die ich je gesehen habe. Danke für deine Antwort.
Abhineet
4

In C ++ 17 werden die neuen Funktionen std :: to_chars und std :: from_chars in den Header charconv eingeführt .

std :: to_chars ist vom Gebietsschema unabhängig, nicht zuweisend und nicht werfend.

Es wird nur eine kleine Teilmenge der Formatierungsrichtlinien bereitgestellt, die von anderen Bibliotheken (z. B. std :: sprintf) verwendet werden.

Von std :: to_chars , dasselbe gilt für std :: from_chars .

Die Garantie, dass std :: from_chars jeden von to_chars formatierten Gleitkommawert exakt wiederherstellen kann, wird nur gegeben, wenn beide Funktionen aus derselben Implementierung stammen

 // See en.cppreference.com for more information, including format control.
#include <cstdio>
#include <cstddef>
#include <cstdlib>
#include <cassert>
#include <charconv>

using Type =  /* Any fundamental type */ ;
std::size_t buffer_size = /* ... */ ;

[[noreturn]] void report_and_exit(int ret, const char *output) noexcept 
{
    std::printf("%s\n", output);
    std::exit(ret);
}
void check(const std::errc &ec) noexcept
{
    if (ec ==  std::errc::value_too_large)
        report_and_exit(1, "Failed");
}
int main() {
    char buffer[buffer_size];        
    Type val_to_be_converted, result_of_converted_back;

    auto result1 = std::to_chars(buffer, buffer + buffer_size,  val_to_be_converted);
    check(result1.ec);
    *result1.ptr = '\0';

    auto result2 = std::from_chars(buffer, result1.ptr, result_of_converted_back);
    check(result2.ec);

    assert(val_to_be_converted == result_of_converted_back);
    report_and_exit(0, buffer);
}

Obwohl es von Compilern nicht vollständig implementiert wird, wird es definitiv implementiert.

JiaHao Xu
quelle
0

Ich habe diese praktische Klasse irgendwo hier bei StackOverflow gestohlen, um alles, was streambar ist, in einen String umzuwandeln:

// make_string
class make_string {
public:
  template <typename T>
  make_string& operator<<( T const & val ) {
    buffer_ << val;
    return *this;
  }
  operator std::string() const {
    return buffer_.str();
  }
private:
  std::ostringstream buffer_;
};

Und dann benutzt du es als;

string str = make_string() << 6 << 8 << "hello";

Ziemlich geschickt!

Außerdem verwende ich diese Funktion, um Zeichenfolgen in Streams zu konvertieren, obwohl dies nicht sehr sicher ist, wenn Sie versuchen, eine Zeichenfolge zu analysieren, die keine Zahl enthält. (und es ist auch nicht so klug wie das letzte)

// parse_string
template <typename RETURN_TYPE, typename STRING_TYPE>
RETURN_TYPE parse_string(const STRING_TYPE& str) {
  std::stringstream buf;
  buf << str;
  RETURN_TYPE val;
  buf >> val;
  return val;
}

Benutzen als:

int x = parse_string<int>("78");

Möglicherweise möchten Sie auch Versionen für wstrings.

Viktor Sehr
quelle
5
Genau das macht boost :: lexical_cast. Und Boost macht es in einer allgemeineren Fasion.
Armen Tsirunyan
Richtig, ich habe die erste Antwort überflogen und die boost :: lexical_casts nicht gesehen.
Viktor Sehr