std::string mit format string
-
Hallo,
Ich will eine Funktion schreiben, die aus dem bekannten printf format string einen std::string macht, sprich sowas:
std::string s = toString("Hallo %i %s!", myVar, var2);Ich koennte das nun mit vsprintf loesen (Pseudocode!):
string toString(const char* fmt, ...) { char buffer[256]; va_list args; va_start (args, fmt); vsprintf (buffer, fmt, args); return string(buffer); }Das Problem ist nur: Ich kann nicht wissen, wie gross buffer sein muss. Wie koennte man den Code besser machen?
-
Marlar22 schrieb:
Wie koennte man den Code besser machen?
- Variadic Templates (rekursive Variante)
- Templates für
char-Typen. - Ordentliche STL-Container/
std::string - Weniger Wrapper um Standardbibliotheksfunktionen

- Gar nicht erst schreiben. Dafür gibt es Stringstreams, die viel sicherer und einfacher sind.
-
oder Boost.Format
-
Marlar22 schrieb:
Das Problem ist nur: Ich kann nicht wissen, wie gross buffer sein muss. Wie koennte man den Code besser machen?
Falls du Visual C++ mit MFC hast, und du keine plattformunabhängige Lösung brauchst, dann guck' dir einfach an wie CString::Fromat implementiert ist, und bau genau das für std::string nach.
Und natürlich krümelkacker Vorschlag (Boost.Format) ist gut.
-
Sone schrieb:
Marlar22 schrieb:
Wie koennte man den Code besser machen?
- Variadic Templates (rekursive Variante)
- Templates für
char-Typen. - Ordentliche STL-Container/
std::string - Weniger Wrapper um Standardbibliotheksfunktionen

- Gar nicht erst schreiben. Dafür gibt es Stringstreams, die viel sicherer und einfacher sind.
Die Tipps bringen mir alle nix. Wo sollen mir da hier Templates helfen?
Und wie ein std::string? Ich will doch gerade einen std::string erzeugen.
Und wo gibt es bitte schon so eine Standardbibliotheksfunktion, die genau sowas macht?Der Tipp mit den Stringstreams ist auch nicht wirklich gut, da bei komplexeren Formaten die Stringstreams einfach nur noch unhandlich sind. Ausserdem ist das resetten nervig.
-
da bei komplexeren Formaten die Stringstreams einfach nur noch unhandlich sind
Man schreibt einfach das rein, was man haben moechte. Warum soll das vergleichsweise unhandlicher sein?
Ausserdem ist das resetten nervig
Benutze einfach einen neuen
stringstream.
-
Marlar22 schrieb:
Die Tipps bringen mir alle nix. Wo sollen mir da hier Templates helfen?
"Helfen"? Du wolltest Verbesserungsvorschläge.
Marlar22 schrieb:
Und wie ein std::string? Ich will doch gerade einen std::string erzeugen.
Du sollst damit arbeiten, anstatt mit C-Style Strings. Das ist sicherer und einfacher.
Marlar22 schrieb:
Und wo gibt es bitte schon so eine Standardbibliotheksfunktion, die genau sowas macht?
Genau sowas? Stringstreams. Oder
sprintf.
Edit: Was ich damit meinte ist, wenn du das schon selber machst, mach alles selber. Sonst bringt es nicht mal einen Lerneffekt.Marlar22 schrieb:
Der Tipp mit den Stringstreams ist auch nicht wirklich gut, da bei komplexeren Formaten die Stringstreams einfach nur noch unhandlich sind. Ausserdem ist das resetten nervig.
Darüber lässt sich diskutieren.
-
Marlar22 schrieb:
Die Tipps bringen mir alle nix. Wo sollen mir da hier Templates helfen?
[...]Der Tipp mit den Stringstreams ist auch nicht wirklich gut, da bei komplexeren Formaten die Stringstreams einfach nur noch unhandlich sind. Ausserdem ist das resetten nervig.
Quasi direkt aus der eng. Wikipedia ("Variadic templates") abgeschrieben. Hat allerdings den Makel, dass es variadic templates und stringstream benutzt...
#include <iostream> #include <stdexcept> #include <sstream> void stringf_helper(std::ostringstream& os, const char *s){ while (*s) { if (*s == '%' && *(++s) != '%') throw std::runtime_error("invalid format string: missing arguments"); os << *s++; } } template<typename T, typename... Args> void stringf_helper(std::ostringstream& os, const char *s, T value, Args... args){ while (*s) { if (*s == '%' && *(++s) != '%') { os << value; ++s; stringf_helper(os, s, args...) return; } os << *s++; } throw std::logic_error("extra arguments provided to stringff"); } template<typename T, typename... Args> std::string stringf(const char* fmt, T val, Args... args){ std::ostringstream os; stringf_helper(os, fmt, val, args...); return os.str(); } std::string stringf(const char* fmt){ std::ostringstream os; stringf_helper(os, fmt); return os.str(); } int main(){ int v = 42; const std::string v2 = "Furble Wurble"; try{ const std::string s = stringf("Hallo, %s! %i\n", v2, v); const std::string s2 = stringf("Leider ist %i egal, was hinter dem %% steht! (%q jedenfalls!)\n", "voellig", "Fast"); std::cout << s << s2; } catch(const std::exception& ex){ std::cerr << "Exception caught: " << ex.what() << '\n'; return -1; } }Das ganze bringt im Großen und Ganzen wenig...aber zeigt evtl. in welche Richtung Du gehen könntest...
-
Marlar22 schrieb:
Ich will eine Funktion schreiben, die aus dem bekannten printf format string einen std::string macht, sprich sowas:
std::string s = toString("Hallo %i %s!", myVar, var2);std::string s = str( boost::format("Hallo %1 %2!") % myVar % var2 );(oder so ähnlich)
Man muss das Rad ja nicht neu erfinden.
-
@Sone: Du bist ziemlich jung, oder?

@krümelkacker und hustbaer: Danke! Die einzigen 2 brauchbaren Antworten im Thread. Genau so hab ich mir das vorgestellt.
Diese Variadic Templates sind ja nicht nur Overkill und haesslich, sondern ich kann sie eh nicht verwenden, da wir kein C++11 benutzen.
Und wer ernsthaft behauptet stringstreams sind so elegant und kompakt wie die printf Formatbezeichner, lebt etwas in einer Traumwelt. Koennt ja mal diese Aufrufe per Stringstreams nachbauen:
string s1 = toString("%06i %07i %2i %5.2lf D", a, b, c, d);
string s2 = toString("%02f %02f %2i E", a, b, c);Grauenhaft lange mit Stringstreams.

-
Marlar22 schrieb:
Grauenhaft lange mit Stringstreams.

Klar, dafür sparst du dir halt ein Wochenende nach einem komischen Absturz zu suchen weil irgendjemand einen double in einen float geändert hat und die jeweiligen Formatspecifier nicht angepasst hat.
Die korrekte Lösung wurde schon genannt: Boost.Format
-
Marlar22 schrieb:
Und wer ernsthaft behauptet stringstreams sind so elegant und kompakt wie die printf Formatbezeichner, lebt etwas in einer Traumwelt. Koennt ja mal diese Aufrufe per Stringstreams nachbauen:
string s1 = toString("%06i %07i %2i %5.2lf D", a, b, c, d);
string s2 = toString("%02f %02f %2i E", a, b, c);Grauenhaft lange mit Stringstreams.

Du bist kein C++-Programmierer

Übrigens kann daslim ersten Format-String weg.
C++-Version:std::stringstream stream; stream << std::setfill('0')//Mehr Freiheiten, was dieses Füllzeichen betrifft << std::setw(6) << a << ' ' //Typsicher und elegant << std::setw(7) << b << ' ' // ... << std::setw(2) << std::setfill(' ') << c << ' ' << std::setw(5) << std::fixed << std::setprecision(2) << d << " D";
-
Sone schrieb:
Du bist kein C++-Programmierer

Und du bist ein Idiot. Halt doch endlich mal die Klappe.

Sone schrieb:
//Typsicher und elegantWait, what?
-
Kellerautomat schrieb:
Sone schrieb:
Du bist kein C++-Programmierer

Und du bist ein Idiot. Halt doch endlich mal die Klappe.

Was war denn hier schon wieder falsch!??!
-
War alles richtig. Kellerautomat weiß einfach nicht, dass man den echten C++ - Programmierer daran erkennt, dass er cout/stringstreams anstelle von printf/sprintf benutzt.
-
Benehmt euch. Oder klärt das privat.
-
pumuckl schrieb:
Benehmt euch. Oder klärt das privat.
Tut mir Leid.

Die Frage des TEs ist inzwischen ja beantwortet worden (ich wollte nur nicht, dass er mit der falschen Vorstellung lebe, Stringstreams seien eine Katastrophe/o.ä.).
-
pumuckl schrieb:
Benehmt euch. Oder klärt das privat.
Lustig.
Sone spammt hier permanent rum, sinnlose Scheisse über sinnlose Scheisse.Wenn man ihn deswegen anmotzt kommt bloss "klärt das privat".
Wie wär's es nicht privat sondern for(u)mell zu klären und ihn einfach zu sperren?
-
Belli schrieb:
Kellerautomat weiß einfach nicht, dass man den echten C++ - Programmierer daran erkennt, dass er cout/stringstreams anstelle von printf/sprintf benutzt.
thx, ymmd!

-
hustbaer schrieb:
pumuckl schrieb:
Benehmt euch. Oder klärt das privat.
Lustig.
Sone spammt hier permanent rum, sinnlose Scheisse über sinnlose Scheisse.Wenn man ihn deswegen anmotzt kommt bloss "klärt das privat".
Danke.
-
Swordfish schrieb:
Belli schrieb:
Kellerautomat weiß einfach nicht, dass man den echten C++ - Programmierer daran erkennt, dass er cout/stringstreams anstelle von printf/sprintf benutzt.
thx, ymmd!

Eigentlich meinte ich, den erkennt man daran dass er den Code schön komplex machen will, was wiederum ein Scherz war.
Aber cool zu sehen, wie hier alles interpretiert wird... oO