Ich muss Format std::string
mit sprintf
und in Datei - Stream senden. Wie kann ich das machen?
c++
string
formatting
stdstring
c++-standard-library
Max Frai
quelle
quelle
boost::format
(wie Kennytms Lösung hier verwendet ).boost::format
unterstützt auch bereits C ++ - Stream-Operatoren! Beispiel :cout << format("helloworld. a=%s, b=%s, c=%s") % 123 % 123.123 % "this is a test" << endl;
.boost::format
hat die wenigsten Codezeilen ... wird von Experten begutachtet und lässt sich gut in C ++ - Streams integrieren.std::format
wurde zu C ++ 20 BTW hinzugefügt: stackoverflow.com/a/57286312/895245 Awesome!C++20
erst gestern einen Artikel gelesen und gesehen, dass er (zum millionsten Mal)C++20
kopiert wurde,boost
indem ich ihnstd::format
zurC++20
Spezifikation hinzufügte ! Ich war sehr sehr glücklich! Fast jede C ++ - Datei, die ich in den letzten 9 Jahren geschrieben habe, wurde verwendetboost::format
. Das Hinzufügen einer offiziellen Ausgabe im Printf-Stil zu Streams in C ++ wird IMO für ganz C ++ einen langen Weg gehen.Antworten:
Sie können dies nicht direkt tun, da Sie keinen Schreibzugriff auf den zugrunde liegenden Puffer haben (bis C ++ 11; siehe Dietrich Epps Kommentar ). Sie müssen es zuerst in einem C-String tun und dann in einen std :: string kopieren:
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:
quelle
char buf[100];
macht diese Lösung nicht sehr robust. Aber die wesentliche Idee ist da.asprintf
, das eine neue Zeichenfolge mit genügend Speicherplatz für das Ergebnis zuweist. Kopieren Sie das dann auf ein,std::string
wenn Sie möchten, und denken Sie anfree
das Original. Es ist auch möglich, dies in ein Makro einzufügen, damit jeder gute Compiler dabei hilft, das Format für Sie zu validieren - Sie möchten nicht angeben,double
wo a%s
erwartet wirdModernes C ++ macht dies super einfach.
C ++ 20
C ++ 20 wird eingeführt
std::format
, mit dem Sie genau das tun können. Es werden Ersatzfelder verwendet, die denen in Python ähneln :Lesen Sie die vollständige Dokumentation ! Es ist eine enorme Verbesserung der Lebensqualität.
C ++ 11
Mit C ++ 11 s
std::snprintf
, wurde dies bereits eine ziemlich einfache und sichere Aufgabe.Das obige Code-Snippet ist unter CC0 1.0 lizenziert .
Zeile für Zeile Erklärung:
Ziel: Schreibe eine
char*
durchVerwendungstd::snprintf
und dann konvertierendas zu einstd::string
.Zuerst bestimmen wir die gewünschte Länge des char-Arrays unter Verwendung einer speziellen Bedingung in
snprintf
. Von cppreference.com :Dies bedeutet, dass die gewünschte Größe die Anzahl der Zeichen plus eins ist , sodass der Nullterminator hinter allen anderen Zeichen steht und vom Zeichenfolgenkonstruktor wieder abgeschnitten werden kann. Dieses Problem wurde von @ alexk7 in den Kommentaren erklärt.
snprintf
gibt eine negative Zahl zurück, wenn ein Fehler aufgetreten ist. Daher prüfen wir, ob die Formatierung wie gewünscht funktioniert hat. Wenn Sie dies nicht tun, kann dies zu stillen Fehlern oder zur Zuweisung eines großen Puffers führen, wie @ead in den Kommentaren hervorhebt.Als nächstes weisen wir ein neues Zeichenarray zu und weisen es einem zu
std::unique_ptr
. Dies wird im Allgemeinen empfohlen, da Sie es nichtdelete
erneut manuell ausführen müssen.Beachten Sie, dass dies keine sichere Methode zum Zuweisen eines
unique_ptr
mit benutzerdefinierten Typen ist, da Sie den Speicher nicht freigeben können, wenn der Konstruktor eine Ausnahme auslöst!Danach können wir natürlich nur
snprintf
für den vorgesehenen Verwendungszweck verwenden und den formatierten String in das schreibenchar[]
.Schließlich erstellen wir ein neues und geben es zurück, wobei wir
std::string
sicherstellen, dass der Null-Terminator am Ende weggelassen wird.Sie können ein Beispiel in Aktion sehen hier .
Wenn Sie auch
std::string
in der Argumentliste verwenden möchten, werfen Sie einen Blick auf diesen Kern .Zusätzliche Informationen für Visual Studio- Benutzer:
Wie in erklärt diese Antwort , umbenannt Microsoft
std::snprintf
auf_snprintf
(ja, ohnestd::
). MS setzt es weiter als veraltet und empfiehlt, es_snprintf_s
stattdessen zu verwenden ,_snprintf_s
akzeptiert jedoch nicht, dass der Puffer Null oder kleiner als die formatierte Ausgabe ist, und berechnet in diesem Fall nicht die Ausgabelänge. Um die Verfallswarnungen während der Kompilierung zu entfernen, können Sie die folgende Zeile oben in die Datei einfügen, die Folgendes enthält_snprintf
:Abschließende Gedanken
Viele Antworten auf diese Frage wurden vor C ++ 11 geschrieben und verwenden feste Pufferlängen oder Variablen. Wenn Sie nicht mit alten Versionen von C ++ feststecken, würde ich die Verwendung dieser Lösungen nicht empfehlen. Im Idealfall gehen Sie den C ++ 20-Weg.
Da die C ++ 11-Lösung in dieser Antwort Vorlagen verwendet, kann sie viel Code generieren, wenn sie häufig verwendet wird. Sofern Sie nicht für eine Umgebung mit sehr begrenztem Speicherplatz für Binärdateien entwickeln, ist dies kein Problem und stellt in Bezug auf Klarheit und Sicherheit immer noch eine enorme Verbesserung gegenüber den anderen Lösungen dar.
Wenn die Raumeffizienz sehr wichtig ist, können diese beiden Lösungen mit vargs und vsnprintf nützlich sein. Verwenden Sie keine Lösungen mit festen Pufferlängen, da dies nur zu Problemen führt.
quelle
return string(&buf[0], size);
oder etwas Ähnliches. Zweitens würde eine solche C-Zeichenfolge undefiniertes Verhalten verursachen, da der Vektor, der die Werte enthält, auf die Sie zeigen, bei der Rückgabe ungültig wird. Drittens, als ich anfing, C ++ zu lernen, definierte der Standard nicht, in welcher Reihenfolge Elemente in einem gespeichert werden musstenstd::vector
, sodass der Zugriff auf seinen Speicher über einen Zeiger ein undefiniertes Verhalten war. Jetzt würde es funktionieren, aber ich sehe keinen Vorteil darin, es so zu machen.std::string
werden aus der implizit konvertiert Vektor (konstruiert werden Kopie Initialisierung ), die dann als Kopie zurückgegeben wird, da die Funktionssignatur vorschlägt. Auch die Elemente von astd::vector
werden und sollten immer zusammenhängend gespeichert werden . Aber ich gehe davon aus, dass dies möglicherweise keinen Nutzen bringt.return string(buf.get(), buf.get() + size);
sollte so seinreturn string(buf.get(), buf.get() + size - 1);
, dass Sie am Ende eine Zeichenfolge mit einem Nullzeichen erhalten. Ich fand dies bei gcc 4.9 der Fall.C ++ 11-Lösung, die
vsnprintf()
intern verwendet:Ein sicherer und effizienter Ansatz (ich habe ihn getestet und er ist schneller):
Der
fmt_str
Wert wird übergeben, um den Anforderungen von zu entsprechenva_start
.HINWEIS: Die "sicherere" und "schnellere" Version funktioniert auf einigen Systemen nicht. Daher sind beide noch aufgeführt. Außerdem hängt "schneller" vollständig davon ab, ob der Vorbelegungsschritt korrekt ist, andernfalls wird
strcpy
er langsamer.quelle
size
in jeder Iteration zuzunehmen , wenn Sie sie beim ersten Aufruf von erhalten könnenvsnprintf()
.boost::format()
bietet die gewünschte Funktionalität:Ab der Übersicht über die Boost-Formatbibliotheken:
quelle
C ++ 20 wird Folgendes enthalten,
std::format
dassprintf
in Bezug auf die API ähnelt, jedoch vollständig typsicher ist, mit benutzerdefinierten Typen arbeitet und eine Python-ähnliche Format-String-Syntax verwendet. So können Sie es formatierenstd::string
und in einen Stream schreiben:oder
Alternativ können Sie die {fmt} -Bibliothek verwenden, um eine Zeichenfolge zu formatieren und in
stdout
einen Dateistream auf einmal zu schreiben :Die
sprintf
meisten anderen Antworten hier verwenden leider varargs und sind von Natur aus unsicher, es sei denn, Sie verwenden so etwas wie dasformat
Attribut von GCC , das nur mit Zeichenfolgen im Literalformat funktioniert. Im folgenden Beispiel können Sie sehen, warum diese Funktionen unsicher sind:Wo
string_format
ist eine Implementierung aus der Antwort von Erik Aronesty. Dieser Code wird kompiliert, stürzt jedoch höchstwahrscheinlich ab, wenn Sie versuchen, ihn auszuführen:Haftungsausschluss : Ich bin der Autor von {fmt} und C ++ 20
std::format
.quelle
error: 'fmt' has not been declared
fmt
ähnliche Implementierung wurde zu C ++ 20 hinzugefügt! stackoverflow.com/a/57286312/895245 fmt beansprucht derzeit Unterstützung dafür. Tolle Arbeit!Wenn Sie nur eine printf-ähnliche Syntax wünschen (ohne printf selbst aufzurufen), schauen Sie sich das Boost-Format an .
quelle
Ich habe mein eigenes mit vsnprintf geschrieben, damit es einen String zurückgibt, anstatt meinen eigenen Puffer erstellen zu müssen.
So können Sie es wie verwenden
quelle
vsnprintf
direkt in die Zeichenfolge verwendet werden kann.std::unique_ptr<char[]> buffer (new char[size]);
Um
std::string
im Sprintf- Format zu formatieren , rufen Siesnprintf
(Argumentenullptr
und0
) auf, um die benötigte Pufferlänge zu erhalten. Schreiben Sie Ihre Funktion mit einer variablen C ++ 11-Vorlage wie folgt:Kompilieren Sie mit C ++ 11-Unterstützung, zum Beispiel in GCC:
g++ -std=c++11
Verwendungszweck:
quelle
char buf[length + 1];
stattchar* buf = new char[length + 1];
?char[]
undchar*
with new besteht darin, dass im ersteren Fall buf auf Stack zugewiesen wird. Es ist in Ordnung für kleine Puffer, aber da wir die Größe der resultierenden Zeichenfolge nicht garantieren können, ist die Verwendung etwas bessernew
.string_sprintf("value: %020000000d",5)
Drucken Sie beispielsweise auf meinem Computer eine unverschämte Anzahl führender Nullen vor Nummer 5, Core-Dumps, wenn Sie ein Array auf einem Stapel verwenden, aber funktionieren Sienew char[length + 1]
std::move
überflüssig ist .[edit: 20/05/25] noch besser ...:
In der Kopfzeile:
Die Funktion
PRINTSTRING(r)
besteht darin, die Benutzeroberfläche oder das Terminal oder spezielle Ausgabeanforderungen zu berücksichtigen#ifdef _some_flag_
. Die Standardeinstellung lautet:[edit '17 / 8/31] Hinzufügen einer variadic templated version 'vtspf (..)':
<<
Dies ist effektiv eine durch Kommas getrennte Version (anstelle) der manchmal behindernden Operatoren, die wie folgt verwendet werden:[Bearbeiten] Angepasst, um die Technik in Erik Aronestys Antwort (oben) zu nutzen:
[vorherige Antwort]
Eine sehr späte Antwort, aber für diejenigen, die wie ich den 'Sprintf'-Weg mögen: Ich habe geschrieben und benutze die folgenden Funktionen. Wenn es Ihnen gefällt, können Sie die% -Optionen erweitern, um sie besser an die Sprint-Optionen anzupassen. Die dort sind derzeit für meine Bedürfnisse ausreichend. Sie verwenden stringf () und stringfappend () wie sprintf. Denken Sie daran, dass die Parameter für ... POD-Typen sein müssen.
quelle
fmt
als Referenz funktioniert es gut. (Aber ich nehme an, die Leute werden mit Spielzeug spielen wollen, also ...) Wenn es andere vermeintliche 'Bugs' gibt, könnten Sie das bitte näher erläutern?So macht es Google:
StringPrintf
(BSD-Lizenz)und Facebook machen es auf ganz ähnliche Weise:
StringPrintf
(Apache-Lizenz)Beide bieten auch eine bequeme
StringAppendF
.quelle
Meine zwei Cent zu dieser sehr beliebten Frage.
Um die Manpage
printf
ähnlicher Funktionen zu zitieren :Mit anderen Worten, eine vernünftige C ++ 11-Implementierung sollte wie folgt aussehen:
Es funktioniert ganz gut :)
Variadische Vorlagen werden nur in C ++ 11 unterstützt. Die Antwort von Pixelpoint zeigt eine ähnliche Technik unter Verwendung älterer Programmierstile.
Es ist seltsam, dass C ++ so etwas nicht sofort einsatzbereit hat. Sie haben kürzlich hinzugefügt
to_string()
, was meiner Meinung nach ein großer Schritt nach vorne ist. Ich frage mich, ob sie irgendwann einen.format
Operator zumstd::string
...Bearbeiten
Wie alexk7 hervorhob, wird A
+1
für den Rückgabewert von benötigtstd::snprintf
, da wir Platz für das\0
Byte benötigen . Intuitiv führt bei den meisten fehlenden Architekturen+1
dazu, dass dierequired
Ganzzahl teilweise mit a überschrieben wird0
. Dies geschieht nach der Auswertungrequired
als Istparameter fürstd::snprintf
, daher sollte der Effekt nicht sichtbar sein.Dieses Problem könnte sich jedoch beispielsweise bei der Compileroptimierung ändern: Was passiert, wenn der Compiler beschließt, ein Register für die
required
Variable zu verwenden? Dies ist die Art von Fehlern, die manchmal zu Sicherheitsproblemen führen.quelle
bytes
Puffers hinaus, wahrscheinlich über dierequired
Ganzzahl (die zum Glück zu diesem Zeitpunkt bereits ausgewertet ist).nullptr
als Pufferargument übergeben, wodurch diechar b;
Zeile in Ihrem Code entfernt wird. ( Quelle )Verwenden von C99 snprintf und C ++ 11
quelle
Getestet, Antwort auf die Produktionsqualität
Diese Antwort behandelt den allgemeinen Fall mit standardkonformen Techniken. Der gleiche Ansatz wird als Beispiel auf CppReference.com am Ende ihrer Seite angegeben. Im Gegensatz zu ihrem Beispiel entspricht dieser Code den Anforderungen der Frage und wird in Robotik- und Satellitenanwendungen vor Ort getestet. Es hat auch das Kommentieren verbessert. Die Designqualität wird weiter unten erläutert.
Vorhersagbare lineare Effizienz
Zwei Durchgänge sind für eine sichere, zuverlässige und vorhersehbare wiederverwendbare Funktion gemäß den Fragenspezifikationen erforderlich. Vermutungen über die Verteilung der Größe von Variablen in einer wiederverwendbaren Funktion sind ein schlechter Programmierstil und sollten vermieden werden. In diesem Fall sind beliebig große Darstellungen variabler Länge von Variablen ein Schlüsselfaktor bei der Wahl des Algorithmus.
Ein erneuter Versuch beim Überlauf ist exponentiell ineffizient. Dies ist ein weiterer Grund, der erörtert wurde, als das C ++ 11-Standardkomitee den obigen Vorschlag erörterte, einen Probelauf bereitzustellen, wenn der Schreibpuffer Null ist.
In der obigen produktionsfertigen Implementierung ist der erste Lauf ein solcher Trockenlauf, um die Zuordnungsgröße zu bestimmen. Es erfolgt keine Zuordnung. Das Parsen von printf-Anweisungen und das Lesen von vargs wurde über Jahrzehnte äußerst effizient gemacht. Wiederverwendbarer Code sollte vorhersehbar sein, auch wenn eine kleine Ineffizienz für triviale Fälle geopfert werden muss.
Sicherheit und Zuverlässigkeit
Andrew Koenig sagte nach seinem Vortrag auf einer Veranstaltung in Cambridge zu einer kleinen Gruppe von uns: "Benutzerfunktionen sollten sich nicht darauf verlassen, dass ein Fehler für außergewöhnliche Funktionen ausgenutzt wird." Wie üblich hat sich seine Weisheit seitdem in der Aufzeichnung als wahr erwiesen. Behobene und geschlossene Sicherheitslücken weisen häufig auf Wiederholungshacks in der Beschreibung des vor dem Fix ausgenutzten Lochs hin.
Dies wird im Überarbeitungsvorschlag für formale Standards für die Nullpufferfunktion in Alternative zu Sprintf, C9X-Überarbeitungsvorschlag , ISO IEC-Dokument WG14 N645 / X3J11 96-008 erwähnt . Eine willkürlich lange Zeichenfolge, die gemäß der Druckanweisung "% s" im Rahmen der dynamischen Speicherverfügbarkeit eingefügt wird, ist keine Ausnahme und sollte nicht zur Erzeugung von "nicht außergewöhnlichen Funktionen" verwendet werden.
Betrachten Sie den Vorschlag neben dem Beispielcode, der unten auf der Seite C ++ Reference.org angegeben ist, auf die im ersten Absatz dieser Antwort verwiesen wird.
Auch das Testen von Fehlerfällen ist selten so robust wie Erfolgsfälle.
Portabilität
Alle großen Betriebssystemanbieter bieten Compiler an, die std :: vsnprintf als Teil der c ++ 11-Standards vollständig unterstützen. Hosts, auf denen Produkte von Anbietern ausgeführt werden, die keine Distributionen mehr verwalten, sollten aus vielen Gründen mit g ++ oder clang ++ ausgestattet sein.
Stapelverwendung
Die Stapelverwendung im ersten Aufruf von std :: vsnprintf ist kleiner oder gleich der des zweiten Aufrufs und wird freigegeben, bevor der zweite Aufruf beginnt. Wenn der erste Aufruf die Stapelverfügbarkeit überschreitet, schlägt auch std :: fprintf fehl.
quelle
C ++ 20
std::format
Es ist angekommen! Die Funktion wird unter folgender Adresse beschrieben: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r9.html und verwendet eine Python-ähnliche
.format()
Syntax.Ich erwarte, dass die Verwendung wie folgt sein wird:
Ich werde es versuchen, wenn der Support bei GCC eintrifft. GCC 9.1.0
g++-9 -std=c++2a
unterstützt ihn immer noch nicht.Die API fügt einen neuen
std::format
Header hinzu:Die vorhandene
fmt
Bibliothek behauptet, sie zu implementieren, wenn Sie die Polyfüllung benötigen: https://github.com/fmtlib/fmtund wurde bereits erwähnt unter: std :: string Formatierung wie sprintf
quelle
Basierend auf der Antwort von Erik Aronesty:
Dies vermeidet die Notwendigkeit,
const
von dem Ergebnis,.c_str()
das in der ursprünglichen Antwort enthalten war, abzuwerfen.quelle
quelle
_vscprintf
ist. Ich denke, Sie sollten diese Antwort näher erläutern.string hat nicht das, was du brauchst, aber std :: stringstream. Verwenden Sie einen Stringstream, um den String zu erstellen und den String dann zu extrahieren. Hier ist eine umfassende Liste der Dinge, die Sie tun können. Zum Beispiel:
Sie erhalten 10 Dezimalstellen Genauigkeit, wenn Sie ein Double oder Float drucken.
quelle
Sie könnten dies versuchen:
quelle
Wenn Sie sich auf einem System mit asprintf (3) befinden , können Sie es einfach umbrechen :
quelle
format
, da sie gcc anweist, die Arten der Argumente zu überprüfen und mit -Wall eine anständige Warnung zu geben:std::string format(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
va_end
. "Wenn va_end nicht aufgerufen wird, bevor eine Funktion, die va_start oder va_copy aufruft, zurückkehrt, ist das Verhalten undefiniert." - docsthrow std::bad_alloc();
, da ich in meiner Codebasis keine C ++ - Ausnahmen verwende. Für Leute, die dies tun, können sie ihn einfach basierend hinzufügen auf den Quellkommentar und Ihren Kommentar hier.Dies ist der Code, den ich dazu in meinem Programm verwende ... Es ist nichts Besonderes, aber es macht den Trick ... Beachten Sie, dass Sie Ihre Größe gegebenenfalls anpassen müssen. MAX_BUFFER ist für mich 1024.
quelle
vsnprintf
direkt in die Zeichenfolge verwendet werden kann.Übernahm die Idee aus der Antwort von Dacav und Pixelpoint . Ich habe ein bisschen rumgespielt und das bekommen:
Mit vernünftiger Programmierpraxis glaube ich, dass der Code ausreichen sollte, aber ich bin immer noch offen für sicherere Alternativen, die immer noch einfach genug sind und kein C ++ 11 erfordern würden.
Und hier ist eine andere Version, die einen Anfangspuffer verwendet, um einen zweiten Aufruf zu verhindern,
vsnprintf()
wenn der Anfangspuffer bereits ausreicht.(Es stellt sich heraus, dass diese Version der Antwort von Piti Ongmongkolkul ähnlich ist , nur dass sie nicht verwendet
new
unddelete[]
beim Erstellen auch eine Größe angibtstd::string
.Die Idee hier ist, den Stack nicht über den Heap zu verwenden
new
unddelete[]
zu implizieren, da er keine Zuordnungs- und Freigabefunktionen aufrufen muss. Wenn er jedoch nicht ordnungsgemäß verwendet wird, kann es gefährlich sein, Überläufe in einigen (möglicherweise alten oder alten) zu puffern vielleicht nur anfällige) Systeme. Wenn dies ein Problem ist, empfehle ich dringend, stattdessennew
und zudelete[]
verwenden. Beachten Sie, dass das einzige Problem hier die Zuweisungen ist, wie sievsnprintf()
bereits mit Limits aufgerufen werden. Wenn Sie also ein Limit basierend auf der im zweiten Puffer zugewiesenen Größe angeben, werden diese ebenfalls verhindert.)quelle
Ich benutze normalerweise Folgendes:
Nachteil: Nicht alle Systeme unterstützen Vasprint
quelle
Unten leicht modifizierte Version der @ iFreilicht-Antwort, aktualisiert auf C ++ 14 (Verwendung der
make_unique
Funktion anstelle der Rohdeklaration ) und Unterstützung fürstd::string
Argumente hinzugefügt (basierend auf dem Artikel von Kenny Kerr )Ausgabe:
Wenn Sie möchten, können Sie diese Antwort auch mit der Originalantwort zusammenführen.
quelle
Die Poco Foundation- Bibliothek verfügt über eine sehr praktische Formatierungsfunktion, die std :: string sowohl in der Formatzeichenfolge als auch in den Werten unterstützt:
quelle
Sie können die C ++ - Ausgabe in cout mithilfe der iomanip-Headerdatei formatieren. Stellen Sie sicher, dass Sie eine iomanip-Headerdatei einschließen, bevor Sie Hilfsfunktionen wie setprecision, setfill usw. verwenden.
Hier ist ein Codefragment, das ich in der Vergangenheit verwendet habe, um die durchschnittliche Wartezeit in dem Vektor zu drucken, den ich "akkumuliert" habe.
Hier finden Sie eine kurze Beschreibung, wie wir C ++ - Streams formatieren können. http://www.cprogramming.com/tutorial/iomanip.html
quelle
Es kann Probleme geben, wenn der Puffer nicht groß genug ist, um die Zeichenfolge zu drucken. Sie müssen die Länge der formatierten Zeichenfolge bestimmen, bevor Sie dort eine formatierte Nachricht drucken. Ich mache einen eigenen Helfer dafür (getestet unter Windows und Linux GCC ), und Sie können versuchen, es zu verwenden.
String.cpp: http://pastebin.com/DnfvzyKP
String.h: http://pastebin.com/7U6iCUMa
String.cpp:
String.h:
quelle
vsnprintf((char *)dst.data(), dst.size() + 1, format, ap);
- Ist es sicher anzunehmen, dass der Puffer der Zeichenfolge Platz für ein abschließendes Nullzeichen hat? Gibt es Implementierungen, die keine Größe + 1 Zeichen zuweisen? Wäre es sicherer zu tundst.resize(length+1); vsnprintf((char *)dst.data(), dst.size(), format, ap); dst.resize(length);
data
undc_str
ist ein Synonym.quelle
Sehr sehr einfache Lösung.
quelle
Mir ist klar, dass dies schon oft beantwortet wurde, aber das ist prägnanter:
Beispiel:
Siehe auch http://rextester.com/NJB14150
quelle
UPDATE 1 :
fmt::format
Tests hinzugefügtIch habe meine eigenen Untersuchungen zu den hier eingeführten Methoden durchgeführt und dabei diametral entgegengesetzte Ergebnisse erzielt als hier erwähnt.
Ich habe 4 Funktionen über 4 Methoden verwendet:
vsnprintf
+std::unique_ptr
vsnprintf
+std::string
std::ostringstream
+std::tuple
+utility::for_each
fmt::format
Funktion aus derfmt
BibliothekFür das Test-Backend
googletest
hat das verwendet.Die
for_each
Implementierung erfolgt von hier aus: Über Tupel iterierenDie Tests:
Die
UTILITY_SUPPRESS_OPTIMIZATION_ON_VAR
.unsued.hpp :
unused.cpp :
Ergebnisse :
Wie Sie sehen können, ist die Implementierung durch das
vsnprintf
+std::string
gleichfmt::format
, aber schneller als durch dasvsnprintf
+std::unique_ptr
, was schneller ist als durch dasstd::ostringstream
.Die Tests wurden in kompiliert
Visual Studio 2015 Update 3
und laufen aufWindows 7 x64 / Intel Core i7-4820K CPU @ 3.70GHz / 16GB
.quelle