FAQ - Umwandlung nach std::string und zurück



  • Ich schreib sonst mal einen Entwurf.



  • Hier wäre der Entwurf. Ich habe die Konvertierungen von und zu Strings jeweils zusammengefasst, damit die Ähnlichkeit deutlicher wird. Weiterführende Themen wie Fehlerbehandlung oder zusätzliche Parameter von stoi() etc. habe ich der Einfachheit halber weggelassen. Ich wäre froh um Rückmeldungen und allfällige Verbesserungen.

    In C++ gibt es verschiedenste Möglichkeiten, Konvertierungen zwischen Zeichenketten (z.B. std::string ) und arithmetischen Typen (z.B. int , double ) vorzunehmen. Im Folgenden sollen die wichtigsten davon erklärt werden.

    1. Standard-Konvertierungsfunktionen

    Standardbibliotheken, die den C++11-Standard unterstützen, bieten diverse überladene Funktionen im Header <string> an, welche eine direkte Umwandlung zwischen Strings und eingebauten Typen unterstützen. Die Konvertierung von arithmetischen Typen zu Strings erfolgt mit den folgenden überladenen Funktionen:

    • to_string() zur Konvertierung in std::string
    • to_wstring() zur Konvertierung in std::wstring

    In umgekehrter Richtung existieren folgende Funktionen, die jeweils für std::string - und std::wstring -Parameter überladen sind:

    • stoi() für int
    • stol() für long
    • stoll() für long long
    • stoul() für unsigned long
    • stoull() für unsigned long long
    • stof() für float
    • stod() für double
    • stold() für long double

    Die Anwendung sieht folgendermassen aus:

    #include <string>
    
    int main()
    {
        // Zahl nach String
        double      a = 4.72;
        std::string x = std::to_string(a);
    
        // String nach Zahl
        std::string y = "5.67";
        double      b = std::stod(y);
    }
    

    2. Stringstreams

    Eine weitere Möglichkeit zur Umwandlung bietet die Klasse std::stringstream . Falls nur Konvertierungen in eine Richtung erforderlich sind, kann std::ostringstream für Output- und std::istringstream für Input-Streams verwendet werden. Für Wide-Strings ( std::wstring ) existieren entsprechende Klassen mit vorangestelltem "w", z.B. std::wostringstream .

    Streams zahlen sich gegenüber den direkten Umwandlungsfunktionen vor allem dann aus, wenn mehrere Werte verkettet werden oder spezielle Stream-Funktionalität (wie Formatflags) erforderlich ist. Die Handhabung ist ähnlich zu std::cout und std::cin , zum Setzen und Auslesen des Strings können die überladenen Methoden str() verwendet werden.

    #include <sstream>
    #include <string>
    
    int main()
    {
        double a = 4.72;
        int    b = 88;
    
        // Output-Stream: Zahlen zu String zusammenfügen
        std::ostringstream oss;
        oss << a << ' ' << b;
        std::string x = oss.str();
    
        // Input-Stream: Zahlen aus String extrahieren
        std::istringstream iss;
        iss.str("5.67 12"); // oder direkt Konstruktor verwenden
        iss >> a >> b;
    }
    

    3. Boost.LexicalCast

    Boost ist eine Sammlung von C++-Bibliotheken und enthält unter anderem Funktionalität zur Umwandlung zwischen arithmetischen Datentypen und Zeichenketten. Dazu dient das Funktionstemplate boost::lexical_cast<T> , wobei T den Zieltypen der Konvertierung bezeichnet. Die Syntax ist analog zu den C++-Cast-Operatoren wie z.B. static_cast<T> .

    Gegenüber der ersten Variante besteht hier der Vorteil, dass keine C++11-Unterstützung notwendig ist. Im Weiteren ist die Syntax für alle Umwandlungen einheitlich, was generische Programmierung vereinfacht.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
        // Zahl nach String
        double      a = 4.72;
        std::string x = boost::lexical_cast<std::string>(a);
    
        // String nach Zahl
        std::string y = "5.67";
        double      b = boost::lexical_cast<double>(y);
    }
    


  • Finde ich gut, allerdings sollte zumindest bei boost::lexical_cast auf die Fehlerbehandlung kurz eingegangen werden und bei Streams auf die Referenz verwiesen werden, meiner Meinung nach.



  • 314159265358979 schrieb:

    Finde ich gut, allerdings sollte zumindest bei boost::lexical_cast auf die Fehlerbehandlung kurz eingegangen werden und bei Streams auf die Referenz verwiesen werden, meiner Meinung nach.

    Ich schlage vor, Du kopierst und änderst (machst debei die Änderungen kenntlich). Der nächste kopiert und ändert weiter. Und wenn alle Protagonisten damit zufrieden sind, wird's wohl so gut sein, daß es (unter Streichung aller Änderungsvermerke) in die FAQ gehört.



  • Meinst du das erst oder zynisch? 😃



  • Dann kann man auch gleich ein Mercurial-Repository aufsetzen. 😃



  • 314159265358979 schrieb:

    Meinst du das erst oder zynisch? 😃

    Ich glaube an das Gute.
    Ich glaube daran, daß der Artikel schon fast fertig ist und binnen Tagen gegen eine nahezu perfekte Fassung konvergieren wird.



  • volkard schrieb:

    Ich glaube daran, daß der Artikel schon fast fertig ist und binnen Tagen gegen eine nahezu perfekte Fassung konvergieren wird.

    ist der Konvergenzradius denn groß genug? Und ist sicher, dass der Prozess eine ständig steigende Nutzenfunktion zu Folge hat? Gibt es vielleicht mehrere gute Lösungen mit suboptimalen Transienten dazwischen?



  • Finde Nexus Vorschlag schon richtig gut. Ich hab mal versucht, den Text ein bisschen kompakter zu schreiben. Der Code ist identisch außer den öffnenden geschweiften Klammern um jeweils eine Zeile zu sparen.

    Hier einige Möglichkeiten, von int , double usw in std::string (bzw. std::wstring ) und umgekehrt zu konvertieren.

    1. Standard-Konvertierungsfunktionen (nur C++0x, ab GCC 4.?.? oder Visual Studio 2010)

    Im neuen Standard gibt es im Header <string> die Funktionen to_string() und to_wstring() zur Konvertierung von nach std::string bzw. std::wstring .
    Daneben für std::wstring und std::wstring zu den arithmetischen Typen:

    • stoi() für int
    • stol() für long
    • stoll() für long long
    • stoul() für unsigned long
    • stoull() für unsigned long long
    • stof() für float
    • stod() für double
    • stold() für long double

    Anwendung:

    #include <string>
    
    int main() {
        // Zahl nach String
        double      a = 4.72;
        std::string x = std::to_string(a);
    
        // String nach Zahl
        std::string y = "5.67";
        double      b = std::stod(y);
    }
    

    2. Stringstreams

    Wer C++x0 nicht nutzt, kann std::stringstream nehmen. Falls nur Konvertierungen in eine Richtung erforderlich sind, kann std::ostringstream für Output- und std::istringstream für Input-Streams verwendet werden. Für Wide-Strings ( std::wstring ) analog mit vorangestelltem "w", z.B. std::wostringstream .
    Hier lassen sich auch leicht mehrere Werte verkettet werden oder z.B. Formatflags einsetzen. Die Handhabung ist ähnlich zu std::cout und std::cin . Zum Setzen und Auslesen des Strings können die überladenen Methoden str() verwendet werden.

    #include <sstream>
    #include <string>
    
    int main() {
        double a = 4.72;
        int    b = 88;
    
        // Output-Stream: Zahlen zu String zusammenfügen
        std::ostringstream oss;
        oss << a << ' ' << b;
        std::string x = oss.str();
    
        // Input-Stream: Zahlen aus String extrahieren
        std::istringstream iss;
        iss.str("5.67 12"); // oder direkt Konstruktor verwenden
        iss >> a >> b;
    }
    

    3. Boost.LexicalCast

    Boost ist eine beliebte Sammlung von C++-Bibliotheken und enthält unter anderem das Funktionstemplate boost::lexical_cast<T> mit T als Zieltyp der Konvertierung. Die Syntax ist analog zu den C++-Cast-Operatoren wie z.B. static_cast<T> . Die einheitliche Syntax für Umwandlungen vereinfacht generische Programmierung.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main() {
        // Zahl nach String
        double      a = 4.72;
        std::string x = boost::lexical_cast<std::string>(a);
    
        // String nach Zahl
        std::string y = "5.67";
        double      b = boost::lexical_cast<double>(y);
    }
    


  • Crap, doch noch ein paar Schnitzer drin.

    Die letzten zwei Sätze ➡ Die Syntax ist analog zu den C++-Cast-Operatoren wie z.B. static_cast<T> und gut geeignet für generische Programmierung.



  • Nur am Rande: Sollte nicht auch zumindest die Rolle der locale erwähnt werden, weil hier auch doubles/Floats vorkommen.
    Bei ints spielt es ja keine Rolle.

    Just my 2 cents...



  • Allzu kurz finde ich nicht gut, ich würde schon die Vorteile der einzelnen Varianten als solche hervorheben, damit gleich klar wird, wann welche Möglichkeit zu verwenden ist. So lange sind die Beschreibungen in meinem Post nun auch wieder nicht 😉

    Und was den Code anbelangt: Öffnende und schliessende Klammern auf der gleichen Höhe finde ich um einiges übersichtlicher. Ist ja nicht so, dass wir hier unbedingt die eine Zeile sparen müssten.

    Bezüglich Locales: Wäre eine Möglichkeit. Dann würde ich aber auch auf Fehlerbehandlung eingehen. Ich habe solche Dinge wie erwähnt weggelassen, da der Artikel primär eine Übersicht über die verschiedenen Wege zur String-Konvertierung geben soll. Besonders Anfänger sind vielleicht froh, wenn sie gerade die wichtigen Daten auf einen Blick haben. Man könnte aber am Schluss eine Liste mit weiterführenden Links (z.B. über Streams) anfügen.


Anmelden zum Antworten