to_string()



  • Schau dir das Beispiel zu setfill an (statt '*' gibst du dann '0' an).



  • @Alphavirus sagte in to_string():

    Stimmt. Das geht.
    Nur aus Interesse, gibt es auch eine Möglichkeit, eine Zahl mit mehreren führenden Nullen vorweg auszugeben?

    Ja, bei Streams aus der Standardbibliothek wie cout einer ist, lässt sich sowas mithilfe sog. Manipulatoren bewerkstelligen, die an der jeweiligen Stelle während der Ausgabe den Stream entsprechend umkonfigurieren:

    cout << setfill('0') << setw(5) << n;
    

    setfill konfiguriert das gewünschte Füllzeichen und setw die minimale Ausgabelänge z.B. für solche Zahlen. Bedenke, dass das Parameter sind, die im Stream gespeichert werden: Sie gelten nicht nur für die nächste Zahl, sondern für alle folgenden - bis der Stream wieder umkonfiguriert wird.

    Als Neuling solltest du auch wissen, dass es für solche Formatierungen mittlerweile eine modernere Alternative gibt, da die in der Praxis immer etwas klobig in der Anwendung waren. Ab C++20 gibt es std::format und ab C++23 std::print. Damit sähe das dann z.B. so aus:

    std::cout << std::format("{:05}", n);
    

    oder

    std::print("{:05}", n);
    

    Siehe auch hier, wie damit Formatierungen spezifiziert werden.

    Du solltest cout-Formatierungen kennen (viel existierender Code verwendet das), aber wenn du Zugriff auf moderneres C++ hast, würde ich für eigene (Übungs-) Projekte std::format/std::print empfehlen. Die C++-Community ist eh schon extrem lahmarsching, was Neuerungen angeht, da kann man als Anfänger ruhig ein bisschen frischen Wind reinbringen 😉



  • Also Danke erstmal.
    Ich krieg das allerdings nicht zum laufen.
    Der Code:

    #include <iostream>
    using namespace std;
    
    int main () {
    	int n = 005223;
    	cout << setfill('0') << setw(5) << n;
    	cout << format("{:05}", n);
    	cout << print("{:05}", n);
    }
    

    Die Fehlermeldungen:
    7 10 C:\Users\User\Documents\C++\Test\test.cpp [Error] 'setfill' was not declared in this scope

    7 26 C:\Users\User\Documents\C++\Test\test.cpp [Error] 'setw' was not declared in this scope; did you mean 'getw'?

    8 10 C:\Users\User\Documents\C++\Test\test.cpp [Error] 'format' was not declared in this scope

    Muss man mit include was einbinden?


  • Mod

    @Alphavirus sagte in to_string():

    Muss man mit include was einbinden?

    Ja, iomanip. Eine der wichtigsten Sachen beim Lernen von C++ ist, solche Fragen selber beantworten zu können. Abgesehen vom offensichtlichen Google "C++ setfill" kann ich nur empfehlen, dir eine gute Referenz zu suchen. Zwei der größten und besten sind cppreference.com und CplusPlus.com:
    https://en.cppreference.com/w/cpp/io/manip/setfill
    https://cplusplus.com/reference/iomanip/setfill/



  • @Alphavirus sagte in to_string():

    Muss man mit include was einbinden?

    Für std::format wäre das #include <format>. Dafür muss der Compiler allerdings C++20 unterstützen und wenn er das tut, oft erstmal für diesen Sprachstandard konfiguriert werden. Bei GCC und Clang macht man das mit dem Compiler-Parameter -std=c++20 und bei MSVC/Visual Studio z.B. mit -std:c++latest, bzw. stellt den Sprachstandard in den Projekteinstellungen der IDE ein (die sorgt dann dafür dass -std:c++latest an den Compiler übergeben wird).

    Für print benötigt man #include <print> und C++23 (mit-std=c++23 bei GCC/Clang aktivieren, falls unterstützt - nur sehr aktuelle Versionen).
    Auch verwendet man std::print() nicht mit std::cout, sondern das steht für sich alleine:

    std::print("{:05}", n);
    

    Diese Funktion gibt nämlich kein Objekt zurück, dass man über einen std::ostream mit << ausgeben kann, wie z.B. einen std::string, so wie es std::to_string() tut, sondern arbeitet direkt auf der Standardausgabe ("Text-Fenster").



  • Wenn das Format-Zeugs für dich/deinen Compiler nicht verfügbar ist, dann kannst du auch fmtlib nehmen. Das ist im Zweifel vollständiger als die Implementierung, die direkt mit deinem Compiler kommt.

    Schau dir den Link an, da sind auch viele Beispiele, wie man das nutzt. Vor allem kannst du mit dieser Library die format-Features auch alle mit einem älteren Compiler nutzen.



  • @wob sagte in to_string():

    Wenn das Format-Zeugs für dich/deinen Compiler nicht verfügbar ist, dann kannst du auch fmtlib nehmen. Das ist im Zweifel vollständiger als die Implementierung, die direkt mit deinem Compiler kommt.

    Die ist "Header only", oder? Normal würd ich ja sagen Bibliotheken für nen Anfänger erstmal nicht, aber wenn Header reichen, dann geht das schon. Es müssen natürlich Include-Verzeichnisse eingestellt werden (IDE oder Buildsystem) und man hat nen anderen Namen für den Header und der Namespace ist soweit ich weiss fmt statt std. Wenn ich mich aber recht entsinne, dann basiert libfmt nicht auf dem C++-Standard, sondern eher der Standard auf der libfmt (glaube sogar das Standard-Proposal stammt von dem Autor). Insofern eine ganz gute Wahl, wenn man etwas mehr mit solchen Formatierungen macht.



  • @Finnegan sagte in to_string():

    @wob sagte in to_string():

    fmtlib

    Die ist "Header only", oder?

    Jein, siehe https://fmt.dev/11.1/get-started/#installation

    {fmt} provides two CMake targets: fmt::fmt for the compiled library and fmt::fmt-header-only for the header-only library. It is recommended to use the compiled library for improved build times.

    Normal würd ich ja sagen Bibliotheken für nen Anfänger erstmal nicht, aber wenn Header reichen, dann geht das schon.

    Warum nicht? Ich denke, es ist extrem hilfreich, wenn man weiß, wie man fremde Bibliotheken einbindet. Und bei fmtlib ist es nun besonders einfach.

    Ich habe manchmal das Gefühl, dass einige in C++ lieber jedes der vier Räder eines Autos einzeln neu erfinden würden, als eine fertige Bibliothek zu nutzen, während einige NodeJS-Developer sogar eine externe Bibliothek einbinden würden, um zu atmen. (ok, etwas übertrieben vielleicht...)



  • @wob sagte in to_string():

    @Finnegan sagte in to_string():

    Normal würd ich ja sagen Bibliotheken für nen Anfänger erstmal nicht, aber wenn Header reichen, dann geht das schon.

    Warum nicht? Ich denke, es ist extrem hilfreich, wenn man weiß, wie man fremde Bibliotheken einbindet. Und bei fmtlib ist es nun besonders einfach.

    "erstmal" nicht. Stimmt natürlich auch, was du schreibst und sehe ich ich ebenso, ich hatte aber eher den Eindruck, dass @Alphavirus gerade dabei ist, überhaupt erstmal die IDE zu bändigen und sich ein wenig über ein "Hallo Welt" hinauszutasten. Kann aber auch sein, dass ich mich irre 😉

    Ich habe manchmal das Gefühl, dass einige in C++ lieber jedes der vier Räder eines Autos einzeln neu erfinden würden, als eine fertige Bibliothek zu nutzen, während einige NodeJS-Developer sogar eine externe Bibliothek einbinden würden, um zu atmen. (ok, etwas übertrieben vielleicht...)

    Das ist bei C++ schon ziemlich oft ein Krampf. Nicht mit jeder Bibliothek, aber doch häufiger als mir lieb ist. Zig verschiedene Build-Systeme, oft sehr umfangreiche Konfigurationen, transitive Abhängigkeiten (wenn man diese und jene Bibliothek nimmt, muss man auch noch 10 andere mit dazu bauen) und Build-Skripte und Code, die in einem Kontext zwar gut funktionieren und leicht zu kompilieren sind, in einem anderen aber schlichtweg "kaputt" sind. Autotools-basierte Bibliotheken, die primär für unixoide Systeme entwickelt wurden, fallen mir da besonders häufig negativ auf, wenn sie auf/für Windows gebaut werden sollen (bin in beiden Welten unterwegs). Umgekehrt gibt es das natürlich auch. CMake-Projekte sind da noch am angenehmsten, die sind zum Glück bei neueren Entwicklungen auch in der Mehrheit - es sei denn es war jemand so schlau und hat GCC- oder gar linux-spezifische Kommandos und Parameter direkt in den Build-Skripten untergebracht. Kommt leider auch hin und wieder vor (aber eher selten).

    Möglicherweise liegt meine schlechte Erfahrung aber auch daran, dass ich die Bibliotheken gerne komplett aus den Quellen baue und in übergeordneten Build-Skripten sicherstelle, dass alles mit den selben Compiler-Flags gebaut wird (wenn ich mein Projekt z.B. mit LTO baue, dann sollen z.B. alle statischen Bibliotheken mit den selben Flags und ebenfalls mit LTO gebaut worden sein). Dabei sollte das Ganze dann auch noch wenn möglich mit GCC, Clang und MSVC funktionieren. Bis sowas dann läuft, kann man schon eine menge Arbeit in die Integration einer Bibliothek stecken, daher auch meine Aversion 😁

    Ich scheue mich zwar nicht davor und würde auch kein "Rad" neu erfinden, aber das, was bei NodeJS teilweise als "Bibliothek" durchgeht (irgendeinen Substring extrahieren oder sowas) schreibe ich durchaus schonmal selbst in ner halben Stunde runter, weil das manchmal weniger Arbeit ist, als eine Bibliothek einzubinden.

    Hinzu kommt auch, dass die Bibliotheken schließlich auch "mitgepflegt" werden müssen, wenn man die ebenfalls ausliefert. Sicherheitsupdates, Anpassung an API-Änderungen, etc. Da sollten zusätzliche Abhängigkeiten für ernsthafte Projekte schon gut überlegt sein. Das hat allerdings auch den Vorteil, dass ein C++-Entwickler wahrscheinlich eher weiß, was für Code in seinem Projekt alles zur Ausführung kommt. Zumindest welche Bibliotheken beteiligt sind, und woher der Code stammt. Denen schiebt man nicht ganz so einfach bösartigen Code direkt via Paketmanager unter (auch wenn das durchaus schonmal vorkommt - war das nicht was mit xz-utils vor einiger Zeit?) - dafür hat man dann Aufgrund von Komplexität und vielfältiger Möglichkeiten, sich mit C++ selbst in den Fuss zu schießen mehr mit Stabilität und potentiellen selbstgebauten Sicherheitslücken zu kämpfen. Das bekommt man zwar auch in jeder anderen Sprache hin, wenn man nicht weiß was man tut, aber C++ macht es einem schon sehr leicht, das nicht zu wissen 😇



  • @Finnegan sagte in to_string():

    Das ist bei C++ schon ziemlich oft ein Krampf.

    Nicht wie bei Python wo man mittels pip install Foo problemlos Bibliotheken installieren kann.


  • Mod

    @Quiche-Lorraine sagte in to_string():

    @Finnegan sagte in to_string():

    Das ist bei C++ schon ziemlich oft ein Krampf.

    Nicht wie bei Python wo man mittels pip install Foo problemlos Bibliotheken installieren kann.

    ERROR: Cannot install Foo==1.2.3

    The conflict is caused by:
    The user requested Foo==1.2.3
    bar 4.5.6 depends on foobar>=7.8.9
    foobar 7.8.9 depends on py_async_foo==0.9.0
    […30 Zeilen Abhängigkeiten…]
    pythread_foobar 0.1.2 depends on Foo<=1.2.2



  • @Quiche-Lorraine sagte in to_string():

    Nicht wie bei Python wo man mittels pip install Foo problemlos Bibliotheken installieren kann.

    Und vorher hätte man aber besser ein venv anlegen sollen...

    Und wie pflegt man Dependencies der Dependencies und Updates davon?

    Nicht ohne Grund hat man ja auch poetry und "neuerdings" uv erfunden 😉

    Wir hatten gerade heute wieder mal den Fall, dass ein externes Paket von tqdm (einem Fortschrittsbalken!) == a.b.c (mit ==) abhängt, ein anderes Paket auch tqdm verwendet, aber mit >= a.d.e. Und boom! So ein sch..., oftmals sind die Abhängigkeiten viel zu strikt angegeben, sodass man Pakete nicht kombinieren kann. Auch das sehr prominente Beispiel Tensorflow hatte mal irgendeine Abhängigkeit mit fixer Dependency drin, die besser >= hätte sein sollen (ich glaube, es war typing-extensions, ich weiß es nicht mehr sicher), was es effektiv verunmöglicht hat, das mit diversen anderen Bibliotheken zu verwenden. Ist inzwischen aber gefixt.



  • @SeppJ sagte in to_string():

    […30 Zeilen Abhängigkeiten…]

    Wie ich schon schrieb, gerade bei C++ kenne ich gerne den Code, den ich in meinem Programm verwende (muss schließlich am Ende dafür geradestehen), daher bin ich eigentlich sogar dankbar, dass Bibliotheken mitunter so eine Mühe machen. Gerade wenn die beim Kompilieren vor die Wand laufen, muss man sich zwangsläufig so weit mit deren Code befassen, dass man ein besseres Bild von deren Qualität bekommt - und da gibt's selbst bei beschissenen Build-Skripten schonmal einen ganz guten Eindruck 🙂



  • @wob
    Ja stimmt schon

    Aber die Probleme sind meines Erachtens deutlich geringer. Und es ist schon angenehm, wenn Abhängigkeiten direkt mit installiert werden.

    Aber ich nutze jetzt Python nicht so stark, nur zu Administration und Zuhause fürs rumspielen. Ein Konflikt hatte ich schon auf Manjaro zwischen FreeCAD und Tensorflow. Aber dafür gibt es ja venv.


  • Mod

    Das Hautproblem bei Python-Dependencies ist, dass es nur ganz selten Rückwärtskompatibilität gibt. Nicht nur zwischen Bibliotheken, sondern auch in der Sprache selbst. Daher muss immer alles was man braucht auf einem gemeinsamen Stand sein, und wehe wenn man von irgendetwas abhängt, das langsam hinterher klüngelt. Dann ist man leider oft gezwungen, mit Updates zu warten, bis alle Macher nachgezogen haben. Und die Macher selbst haben wahrscheinlich selber das gleiche Problem, dass sie erst auf ihre Abhängigkeiten warten müssen, bis sie damit beginnen können, ihr Produkt auf eine neue Sprachversion anzuheben.

    Bei C++ habe ich solche Probleme äußerst selten bis gar nie. Die meisten Schnittstellen sind sehr stabil, da sie auf C-Primitiven beruhen, und Sprachversion ist nur insofern ein Problem, dass der Compiler die neueste Sprachversion unterstützten muss, die irgendeine Abhängigkeit benötigt. Wenn man die Abhängigkeiten nicht selber compiliert, noch nicht einmal das.

    Aber sonst will ich nix gegen Python gesagt haben, gute Sprache sonst.


Anmelden zum Antworten