std::string Formatierung wie sprintf

Lesezeit: 8 Minuten

stdstring Formatierung wie sprintf
Max Frai

Ich muss formatieren std::string mit sprintf und senden Sie es in den Dateistream. Wie kann ich das machen?

  • @Ockonal — Zum Wohle der Community (ich könnte mich nicht weniger um meinen Vertreter kümmern) schlage ich vor, dass Sie Ihre Auswahl ändern. Der aktuell ausgewählte im ersten Ausschnitt weist einen Fehler auf, der darauf wartet, bei der Verwendung einer beliebigen maximalen Länge zu passieren. Der zweite Ausschnitt ignoriert vollständig Ihren erklärten Wunsch, Vargs wie sprintf zu verwenden. Ich schlage vor, Sie wählen hier die EINZIGE Antwort, die sauber und sicher ist, sich nur auf C++-Standards stützt, getestet und gut kommentiert ist. Dass es meins ist, ist nicht relevant. Es ist objektiv wahr. Siehe stackoverflow.com/questions/2342162/….

    – Douglas Daseeco

    21. September 2018 um 21:31 Uhr

  • @TrevorBoydSmith a std::format wurde übrigens zu C++20 hinzugefügt: stackoverflow.com/a/57286312/895245 Super!

    – Ciro Santilli Путлер Капут 六四事

    31. Juli 2019 um 8:24 Uhr

  • @CiroSantilli Ich habe einen Artikel darüber gelesen C++20 erst gestern und das habe ich gesehen C++20 kopiert boost (zum millionsten Mal) durch Hinzufügen der std::format zum C++20 spezifizieren! Ich habe mich sehr sehr gefreut! Fast jede C++-Datei, die ich in den letzten 9 Jahren geschrieben habe, wurde verwendet boost::format. Das Hinzufügen einer offiziellen Ausgabe im printf-Stil zu Streams in C++ wird IMO für alle C++ einen langen Weg zurücklegen.

    – Trevor Boyd Smith

    31. Juli 2019 um 12:13 Uhr


  • @TrevorBoydSmith Das ist nicht richtig. std::format verwendet Ersetzungsfelder ({}) im Gegensatz zu den %-Art von printf und boost::format. Dies wurde zunächst in der Bibliothek implementiert {fmt} von Victor Zverovich, der auch C++20’s geschrieben hat std::format und hat eine Antwort in diesem sehr Thread.

    – iFreilicht

    15. Oktober 2020 um 10:28 Uhr

stdstring Formatierung wie sprintf
Doug T.

Sie können dies nicht direkt tun, da Sie keinen Schreibzugriff auf den zugrunde liegenden Puffer haben (bis C++ 11; siehe Kommentar von Dietrich Epp). Sie müssen es zuerst in einem C-String tun und es dann in einen std::string kopieren:

  char buff[100];
  snprintf(buff, sizeof(buff), "%s", "Hello");
  std::string buffAsStdStr = buff;

Aber ich bin mir nicht sicher, warum Sie nicht einfach einen String-Stream verwenden würden? Ich gehe davon aus, dass Sie bestimmte Gründe haben, dies nicht einfach zu tun:

  std::ostringstream stringStream;
  stringStream << "Hello";
  std::string copyOfStr = stringStream.str();

  • Der Zauberkeks drin char buf[100]; macht diese Lösung nicht sehr robust. Aber die grundlegende Idee ist da.

    – Johannes Dibling

    26. Februar 2010 um 14:40 Uhr

  • John, Streams sind nicht langsam. Der einzige Grund, warum Streams langsam erscheinen, ist, dass die iostreams standardmäßig mit der Ausgabe von C FILE synchronisiert werden, sodass gemischte cout- und printfs-Dateien korrekt ausgegeben werden. Das Deaktivieren dieses Links (mit einem Aufruf von cout.sync_with_stdio(false)) führt dazu, dass die Streams von c++ stdio übertreffen, zumindest ab MSVC10.

    – Jimbo

    20. Januar 2013 um 21:15 Uhr

  • Der Grund für die Verwendung von Formaten besteht darin, einen Lokalisierer die Satzstruktur für Fremdsprachen neu aufbauen zu lassen, anstatt die Grammatik des Satzes fest zu codieren.

    – Martin Courteaux

    9. Juli 2013 um 14:51 Uhr

  • Aus irgendeinem Grund verwenden andere Sprachen eine printf-ähnliche Syntax: Java, Python (die neue Syntax ist immer noch näher an printf als an streams). Nur C++ fügt unschuldigen Menschen diesen wortreichen Greuel zu.

    – quant_dev

    5. April 2015 um 0:29 Uhr

  • Noch besser, verwenden asprintf, wodurch eine neue Zeichenfolge mit genügend Platz für das Ergebnis zugewiesen wird. Dann kopiere das in eine std::string wenn Sie möchten, und denken Sie daran free das Original. Es ist auch möglich, dies in ein Makro einzufügen, sodass jeder gute Compiler Ihnen hilft, das Format für Sie zu validieren – Sie möchten kein double wo ein %s Es wird erwartet

    – Aaron McDaid

    10. Juli 2015 um 14:35 Uhr

  • schleppend. warum um 1 vergrößern? Und wann gibt diese Funktion -1 zurück?

    – 0xTOTES RINDFLEISCH

    18. Mai 2012 um 10:45 Uhr


  • Sie überschreiben str.c_str()? Ist das nicht gefährlich?

    – Quanten

    22. August 2012 um 15:12 Uhr

  • va_start mit einem Referenzargument hat Probleme auf MSVC. Es schlägt stillschweigend fehl und gibt Zeiger auf den Zufallsspeicher zurück. Verwenden Sie als Problemumgehung std::string fmt anstelle von std::string &fmt oder schreiben Sie ein Wrapper-Objekt.

    – Steve Hanov

    27. August 2012 um 17:53 Uhr

  • Ich würde +1 geben, weil ich weiß, dass dies wahrscheinlich funktionieren wird, je nachdem, wie die meisten std::strings implementiert sind, aber c_str ist nicht wirklich als Ort zum Ändern der zugrunde liegenden Zeichenfolge gedacht. Es soll schreibgeschützt sein.

    – Doug T.

    25. September 2012 um 14:57 Uhr

  • Und um die resultierende Zeichenfolgenlänge vorher zu erhalten, siehe: stackoverflow.com/a/7825892/908336 Ich sehe keinen Sinn darin, zu erhöhen size in jeder Iteration, wenn Sie es beim ersten Aufruf von erhalten können vsnprintf().

    – Masood Khaari

    15. Mai 2013 um 9:12 Uhr


1647119412 136 stdstring Formatierung wie sprintf
kennytm

boost::format() bietet die gewünschte Funktionalität:

Aus der Zusammenfassung der Boost-Formatbibliotheken:

Ein Formatobjekt wird aus einer Formatzeichenfolge konstruiert und erhält dann durch wiederholte Aufrufe von operator% Argumente. Jedes dieser Argumente wird dann in Zeichenfolgen konvertiert, die wiederum gemäß der Formatzeichenfolge zu einer Zeichenfolge kombiniert werden.

#include <boost/format.hpp>

cout << boost::format("writing %1%,  x=%2% : %3%-th try") % "toto" % 40.23 % 50; 
// prints "writing toto,  x=40.230 : 50-th try"

  • Sie können die benötigten Bibliotheken auch aus dem Boost entfernen. Mit einem mitgelieferten Werkzeug.

    – Hassan Syed

    26. Februar 2010 um 16:23 Uhr


  • Boost Format ist nicht nur groß, sondern auch sehr langsam. Sehen zverovich.net/2013/09/07/… und boost.org/doc/libs/1_52_0/libs/spirit/doc/html/spirit/karma/…

    – vitaut

    20. Mai 2014 um 1:43 Uhr

  • Das Einfügen von Boost an beliebiger Stelle in Ihrem Projekt erhöht sofort die Kompilierungszeiten erheblich. Bei großen Projekten spielt es wahrscheinlich keine Rolle. Für kleine Projekte ist Boost eine Belastung.

    – quant_dev

    5. April 2015 um 0:30 Uhr

  • @vitaut Während es ist fürchterlich Ressourcenverbrauch im Vergleich zu den Alternativen. Wie oft formatieren Sie Strings? Wenn man bedenkt, dass es nur ein paar Mikrosekunden dauert und die meisten Projekte es wahrscheinlich nur ein paar Dutzend Mal verwenden, fällt es in einem Projekt, das sich nicht stark auf die Formatierung von Zeichenfolgen konzentriert, nicht auf, oder?

    – AturSams

    17. August 2015 um 12:04 Uhr

  • Leider funktioniert boost::format nicht auf die gleiche Weise: akzeptiert die var_args nicht. Einige Leute möchten, dass der gesamte Code, der sich auf ein einzelnes Programm bezieht, gleich aussieht/die gleichen Redewendungen verwendet.

    – xor007

    26. Oktober 2015 um 14:37 Uhr

C++20 hat std::format was ähnelt sprintf in Bezug auf die API, ist jedoch vollständig typsicher, arbeitet mit benutzerdefinierten Typen und verwendet eine Python-ähnliche Format-String-Syntax. So können Sie formatieren std::string und schreibe es in einen Stream:

std::string s = "foo";
std::cout << std::format("Look, a string: {}", s);

Alternativ könnten Sie verwenden die {fmt}-Bibliothek um einen String zu formatieren und in ihn zu schreiben stdout oder ein Dateistream auf einmal:

fmt::print("Look, a string: {}", s);

Wie für sprintf oder die meisten anderen Antworten hier verwenden leider Varargs und sind von Natur aus unsicher, es sei denn, Sie verwenden so etwas wie GCCs format -Attribut, das nur mit wörtlichen Formatzeichenfolgen funktioniert. Warum diese Funktionen unsicher sind, sehen Sie am folgenden Beispiel:

std::string format_str = "%s";
string_format(format_str, format_str[0]);

wo string_format ist eine Implementierung aus der Antwort von Erik Aronesty. Dieser Code wird kompiliert, aber er wird höchstwahrscheinlich abstürzen, wenn Sie versuchen, ihn auszuführen:

$ g++ -Wall -Wextra -pedantic test.cc 
$ ./a.out 
Segmentation fault: 11

Haftungsausschluss: Ich bin der Autor von {fmt} und C++20 std::format.

  • Sie können die benötigten Bibliotheken auch aus dem Boost entfernen. Mit einem mitgelieferten Werkzeug.

    – Hassan Syed

    26. Februar 2010 um 16:23 Uhr


  • Boost Format ist nicht nur groß, sondern auch sehr langsam. Sehen zverovich.net/2013/09/07/… und boost.org/doc/libs/1_52_0/libs/spirit/doc/html/spirit/karma/…

    – vitaut

    20. Mai 2014 um 1:43 Uhr

  • Das Einfügen von Boost an beliebiger Stelle in Ihrem Projekt erhöht sofort die Kompilierungszeiten erheblich. Bei großen Projekten spielt es wahrscheinlich keine Rolle. Für kleine Projekte ist Boost eine Belastung.

    – quant_dev

    5. April 2015 um 0:30 Uhr

  • @vitaut Während es ist fürchterlich Ressourcenverbrauch im Vergleich zu den Alternativen. Wie oft formatieren Sie Strings? Wenn man bedenkt, dass es nur ein paar Mikrosekunden dauert und die meisten Projekte es wahrscheinlich nur ein paar Dutzend Mal verwenden, fällt es in einem Projekt, das sich nicht stark auf die Formatierung von Zeichenfolgen konzentriert, nicht auf, oder?

    – AturSams

    17. August 2015 um 12:04 Uhr

  • Leider funktioniert boost::format nicht auf die gleiche Weise: akzeptiert die var_args nicht. Einige Leute möchten, dass der gesamte Code, der sich auf ein einzelnes Programm bezieht, gleich aussieht/die gleichen Redewendungen verwendet.

    – xor007

    26. Oktober 2015 um 14:37 Uhr

1647119412 39 stdstring Formatierung wie sprintf
Destroyica

Ich habe meine eigene mit vsnprintf geschrieben, damit sie eine Zeichenfolge zurückgibt, anstatt meinen eigenen Puffer erstellen zu müssen.

#include <string>
#include <cstdarg>

//missing string printf
//this is safe and convenient but not exactly efficient
inline std::string format(const char* fmt, ...){
    int size = 512;
    char* buffer = 0;
    buffer = new char[size];
    va_list vl;
    va_start(vl, fmt);
    int nsize = vsnprintf(buffer, size, fmt, vl);
    if(size<=nsize){ //fail delete buffer and try again
        delete[] buffer;
        buffer = 0;
        buffer = new char[nsize+1]; //+1 for /0
        nsize = vsnprintf(buffer, size, fmt, vl);
    }
    std::string ret(buffer);
    va_end(vl);
    delete[] buffer;
    return ret;
}

Du kannst es also gerne verwenden

std::string mystr = format("%s %d %10.5f", "omg", 1, 10.5);

  • Dadurch wird eine vollständige zusätzliche Kopie der Daten erstellt, die verwendet werden können vsnprintf direkt in die Saite.

    – Muhende Ente

    12. März 2013 um 16:47 Uhr

  • Verwenden Sie den Code in stackoverflow.com/a/7825892/908336, um die resultierende Zeichenfolgenlänge im Voraus zu erhalten. Und Sie können intelligente Zeiger für einen ausnahmesicheren Code verwenden: std::unique_ptr<char[]> buffer (new char[size]);

    – Masood Khaari

    15. Mai 2013 um 9:19 Uhr


  • Ich bin mir nicht sicher, ob dies im Fallback-Fall richtig ist. Ich denke, Sie müssen eine va_copy von vl für das zweite vsnprintf() machen, um die Argumente richtig zu sehen. Ein Beispiel finden Sie unter: github.com/haberman/upb/blob/…

    – Josh Habermann

    2. November 2013 um 18:25 Uhr

995190cookie-checkstd::string Formatierung wie sprintf

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy