{fmt} ist eine Open-Source-Formatierungsbibliothek, die eine schnelle und sichere Alternative zu C stdio und C++ iostreams bietet.
Wenn Ihnen dieses Projekt gefällt, denken Sie bitte über eine Spende an einen der Fonds nach, die den Opfern des Krieges in der Ukraine helfen: https://www.stopputin.net/.
Dokumentation
Spickzettel
Fragen und Antworten: Stellen Sie Fragen zu StackOverflow mit dem Tag fmt.
Versuchen Sie es mit {fmt} im Compiler Explorer.
Einfache Format-API mit Positionsargumenten für die Lokalisierung
Implementierung von C++20 std::format und C++23 std::print
Formatieren Sie die String-Syntax ähnlich dem Python-Format
Schneller IEEE 754-Gleitkommaformatierer mit korrekter Rundung, Kürze und Roundtrip-Garantie unter Verwendung des Dragonbox-Algorithmus
Portable Unicode-Unterstützung
Sichere printf-Implementierung einschließlich der POSIX-Erweiterung für Positionsargumente
Erweiterbarkeit: Unterstützung für benutzerdefinierte Typen
Hohe Leistung: schneller als gängige Standardbibliotheksimplementierungen von (s)printf
, iostreams, to_string
und to_chars
, siehe Geschwindigkeitstests und Konvertieren von hundert Millionen Ganzzahlen in Strings pro Sekunde
Geringe Codegröße, sowohl in Bezug auf den Quellcode, wobei die Mindestkonfiguration aus nur drei Dateien besteht, core.h
, format.h
und format-inl.h
, als auch aus kompiliertem Code; siehe Kompilierzeit und Code-Aufblähung
Zuverlässigkeit: Die Bibliothek verfügt über umfangreiche Tests und wird kontinuierlich überprüft
Sicherheit: Die Bibliothek ist vollständig typsicher, Fehler in Formatzeichenfolgen können zur Kompilierungszeit gemeldet werden, automatische Speicherverwaltung verhindert Pufferüberlauffehler
Benutzerfreundlichkeit: kleine, eigenständige Codebasis, keine externen Abhängigkeiten, freizügige MIT-Lizenz
Portabilität mit konsistenter Ausgabe auf allen Plattformen und Unterstützung für ältere Compiler
Saubere, warnungsfreie Codebasis auch bei hohen Warnstufen wie -Wall -Wextra -pedantic
Standardmäßig Lokalisierungsunabhängigkeit
Optionale Nur-Header-Konfiguration, aktiviert mit dem FMT_HEADER_ONLY
-Makro
Weitere Einzelheiten finden Sie in der Dokumentation.
Auf Stdout drucken (ausführen)
#include <fmt/core.h>int main() { fmt::print("Hallo, Welt!n"); }
Einen String formatieren (ausführen)
std::string s = fmt::format("Die Antwort ist {}.", 42);// s == "Die Antwort ist 42."
Formatieren Sie eine Zeichenfolge mithilfe von Positionsargumenten (Ausführen).
std::string s = fmt::format("Ich wäre lieber {1} als {0}.", "richtig", "glücklich");// s == "Ich wäre lieber glücklich als richtig ."
Datum und Uhrzeit drucken (Ausführung)
#include <fmt/chrono.h>int main() { auto now = std::chrono::system_clock::now(); fmt::print("Datum und Uhrzeit: {}n", jetzt); fmt::print("Time: {:%H:%M}n", now); }
Ausgabe:
Date and time: 2023-12-26 19:10:31.557195597 Time: 19:10
Einen Container drucken (ausführen)
#include <vector>#include <fmt/ranges.h>int main() { std::vector<int> v = {1, 2, 3}; fmt::print("{}n", v); }
Ausgabe:
[1, 2, 3]
Überprüfen Sie eine Formatzeichenfolge zur Kompilierungszeit
std::string s = fmt::format("{:d}", "Ich bin keine Zahl");
Dies führt in C++20 zu einem Kompilierungsfehler, da d
ein ungültiger Formatbezeichner für eine Zeichenfolge ist.
Schreiben Sie eine Datei aus einem einzelnen Thread
#include <fmt/os.h>int main() { auto out = fmt::output_file("guide.txt"); out.print("Don't {}", "Panic"); }
Dies kann 5 bis 9 Mal schneller sein als fprintf.
Drucken Sie mit Farben und Textstilen
#include <fmt/color.h>int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Hallo, {}!n", "world" ); fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | fmt::emphasis::underline, "Olá, {}!n", "Mundo"); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "你好{}!n", "世界"); }
Ausgabe auf einem modernen Terminal mit Unicode-Unterstützung:
Bibliothek | Verfahren | Laufzeit, s |
---|---|---|
libc | printf | 0,91 |
libc++ | std::ostream | 2,49 |
{fmt} 9.1 | fmt::print | 0,74 |
Boost-Format 1.80 | boost::format | 6.26 |
Folly-Format | Torheit::format | 1,87 |
{fmt} ist die schnellste der Benchmark-Methoden, etwa 20 % schneller als printf
.
Die obigen Ergebnisse wurden generiert, indem tinyformat_test.cpp
unter macOS 12.6.1 mit clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT
erstellt und der beste von drei Läufen verwendet wurde. Im Test wird die Formatzeichenfolge "%0.10f:%04d:%+g:%s:%p:%c:%%n"
oder ein Äquivalent 2.000.000 Mal mit einer an /dev/null
gesendeten Ausgabe gefüllt; Weitere Einzelheiten finden Sie in der Quelle.
{fmt} ist bis zu 20-30x schneller als std::ostringstream
und sprintf
bei IEEE754- float
und double
-Formatierung (dtoa-benchmark) und schneller als Double-Conversion und Ryu:
Das Skript bloat-test.py von format-benchmark testet Kompilierzeit und Code-Aufblähung für nicht triviale Projekte. Es generiert 100 Übersetzungseinheiten und verwendet printf()
oder dessen Alternative jeweils fünfmal, um ein mittelgroßes Projekt zu simulieren. Die resultierende ausführbare Dateigröße und Kompilierzeit (Apple Clang Version 15.0.0 (clang-1500.1.0.2.5), macOS Sonoma, Best of Three) wird in den folgenden Tabellen angezeigt.
Optimierter Build (-O3)
Verfahren | Kompilierungszeit, s | Ausführbare Größe, KiB | Reduzierte Größe, KiB |
---|---|---|---|
printf | 1.6 | 54 | 50 |
IOStreams | 25.9 | 98 | 84 |
fmt 83652df | 4.8 | 54 | 50 |
Winzigformat | 29.1 | 161 | 136 |
Boost-Format | 55,0 | 530 | 317 |
{fmt} lässt sich schnell kompilieren und ist hinsichtlich der Binärgröße pro Aufruf mit printf
vergleichbar (innerhalb eines Rundungsfehlers auf diesem System).
Nicht optimierter Build
Verfahren | Kompilierungszeit, s | Ausführbare Größe, KiB | Reduzierte Größe, KiB |
---|---|---|---|
printf | 1.4 | 54 | 50 |
IOStreams | 23.4 | 92 | 68 |
{fmt} 83652df | 4.4 | 89 | 85 |
Winzigformat | 24.5 | 204 | 161 |
Boost-Format | 36.4 | 831 | 462 |
libc
, lib(std)c++
und libfmt
sind alle als gemeinsam genutzte Bibliotheken verknüpft, um nur den Overhead der Formatierungsfunktionen zu vergleichen. Boost Format ist eine reine Header-Bibliothek und bietet daher keine Verknüpfungsoptionen.
Anweisungen zum Erstellen der Bibliothek und zum Ausführen der Komponententests finden Sie unter „Erstellen der Bibliothek“.
Benchmarks befinden sich in einem separaten Repository, format-benchmarks. Um die Benchmarks auszuführen, müssen Sie also zunächst dieses Repository klonen und Makefiles mit CMake generieren:
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake .
Dann können Sie den Geschwindigkeitstest durchführen:
$ make speed-test
oder der Blähtest:
$ make bloat-test
clang-tidy v18 bietet die Modernize-Use-Std-Print-Prüfung, die in der Lage ist, Vorkommen von printf
und fprintf
in fmt::print
zu konvertieren, sofern dies entsprechend konfiguriert ist. (Standardmäßig wird es in std::print
konvertiert.)
0 AD: ein kostenloses, plattformübergreifendes Open-Source-Echtzeit-Strategiespiel
AMPL/MP: eine Open-Source-Bibliothek für mathematische Programmierung
Apples FoundationDB: ein Open-Source-, verteilter, transaktionaler Schlüsselwertspeicher
Aseprite: animierter Sprite-Editor und Pixel-Art-Tool
AvioBook: eine umfassende Suite für den Flugbetrieb
Blizzard Battle.net: eine Online-Gaming-Plattform
Celestia: Echtzeit-3D-Visualisierung des Weltraums
Ceph: ein skalierbares verteiltes Speichersystem
ccache: ein Compiler-Cache
ClickHouse: ein analytisches Datenbankverwaltungssystem
ContextVision: medizinische Bildgebungssoftware
Contour: ein moderner Terminalemulator
CUAUV: Das autonome Unterwasserfahrzeug der Cornell University
Drake: eine Planungs-, Steuerungs- und Analyse-Toolbox für nichtlineare dynamische Systeme (MIT)
Envoy: C++ L7-Proxy und Kommunikationsbus (Lyft)
FiveM: ein Modifikationsframework für GTA V
fmtlog: eine leistungsstarke Protokollierungsbibliothek im fmtlib-Stil mit einer Latenzzeit von Nanosekunden
Folly: Open-Source-Bibliothek von Facebook
GemRB: eine tragbare Open-Source-Implementierung der Infinity Engine von Bioware
Grand Mountain Adventure: ein wunderschönes Open-World-Ski- und Snowboardspiel
HarpyWar/pvpgn: Spieler-gegen-Spieler-Gaming-Netzwerk mit Optimierungen
KBEngine: eine Open-Source-MMOG-Server-Engine
Keypirinha: ein semantischer Launcher für Windows
Kodi (ehemals xbmc): Heimkino-Software
Knuth: Hochleistungs-Bitcoin-Vollknoten
libunicode: eine moderne C++17-Unicode-Bibliothek
MariaDB: relationales Datenbankverwaltungssystem
Microsoft Verona: Programmiersprache für gleichzeitigen Besitz erforschen
MongoDB: verteilte Dokumentendatenbank
MongoDB Smasher: ein kleines Tool zum Generieren randomisierter Datensätze
OpenSpace: ein Open-Source-Astrovisualisierungs-Framework
PenUltima Online (POL): ein MMO-Server, kompatibel mit den meisten Ultima Online-Clients
PyTorch: eine Open-Source-Bibliothek für maschinelles Lernen
quasardb: eine verteilte, leistungsstarke, assoziative Datenbank
Quill: asynchrone Protokollierungsbibliothek mit geringer Latenz
QKW: Aliasing verallgemeinern, um die Navigation zu vereinfachen und komplexe mehrzeilige Terminalbefehlssequenzen auszuführen
redis-cerberus: ein Redis-Cluster-Proxy
redpanda: ein 10x schnellerer Kafka®-Ersatz für geschäftskritische Systeme, geschrieben in C++
rpclib: eine moderne C++ msgpack-RPC-Server- und Client-Bibliothek
Salesforce Analytics Cloud: Business-Intelligence-Software
Scylla: ein Cassandra-kompatibler NoSQL-Datenspeicher, der 1 Million Transaktionen pro Sekunde auf einem einzigen Server verarbeiten kann
Seastar: ein fortschrittliches Open-Source-C++-Framework für leistungsstarke Serveranwendungen auf moderner Hardware
spdlog: Superschnelle C++-Protokollierungsbibliothek
Stellar: Finanzplattform
Touch Surgery: Operationssimulator
TrinityCore: Open-Source-MMORPG-Framework
? Userver-Framework: Asynchrones Open-Source-Framework mit einem umfangreichen Satz an Abstraktionen und Datenbanktreibern
Windows-Terminal: das neue Windows-Terminal
Mehr...
Wenn Ihnen andere Projekte bekannt sind, die diese Bibliothek verwenden, teilen Sie mir dies bitte per E-Mail oder durch Einreichen eines Problems mit.
Warum also noch eine weitere Formatierungsbibliothek?
Für diese Aufgabe gibt es zahlreiche Methoden, von Standardmethoden wie der printf-Funktionsfamilie und iostreams bis hin zu Boost Format- und FastFormat-Bibliotheken. Der Grund für die Erstellung einer neuen Bibliothek ist, dass jede vorhandene Lösung, die ich gefunden habe, entweder schwerwiegende Probleme hatte oder nicht alle Funktionen bereitstellte, die ich brauchte.
Das Gute an printf
ist, dass es ziemlich schnell und leicht verfügbar ist, da es Teil der C-Standardbibliothek ist. Der Hauptnachteil besteht darin, dass keine benutzerdefinierten Typen unterstützt werden. printf
hat auch Sicherheitsprobleme, obwohl diese durch __attribute__ ((format (printf, ...)) in GCC etwas gemildert werden. Es gibt eine POSIX-Erweiterung, die für i18n erforderliche Positionsargumente zu printf
hinzufügt, aber sie ist nicht Teil von C99 und kann möglicherweise auf einigen Plattformen nicht verfügbar sein.
Das Hauptproblem bei iostreams lässt sich am besten anhand eines Beispiels veranschaulichen:
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "n";
Das ist im Vergleich zu printf viel Tipparbeit:
printf("%.2fn", 1.23456);
Matthew Wilson, der Autor von FastFormat, nannte dies „Chevron-Hölle“. iostreams unterstützen von Natur aus keine Positionsargumente.
Das Gute daran ist, dass iostreams benutzerdefinierte Typen unterstützen und sicher sind, obwohl die Fehlerbehandlung umständlich ist.
Dies ist eine sehr leistungsstarke Bibliothek, die sowohl printf
-ähnliche Formatzeichenfolgen als auch Positionsargumente unterstützt. Sein Hauptnachteil ist die Leistung. Laut verschiedener Benchmarks ist es deutlich langsamer als andere hier betrachtete Methoden. Das Boost-Format weist außerdem übermäßig lange Build-Zeiten und schwerwiegende Probleme mit der Code-Aufblähung auf (siehe Benchmarks).
Dies ist eine interessante Bibliothek, die schnell und sicher ist und über Positionsargumente verfügt. Es weist jedoch erhebliche Einschränkungen auf und zitiert seinen Autor:
Drei Merkmale, die im aktuellen Design nicht berücksichtigt werden können, sind:
Führende Nullen (oder jede andere Auffüllung ohne Leerzeichen)
Oktal-/Hexadezimalkodierung
Spezifikation der Laufzeitbreite/-ausrichtung
Es ist außerdem ziemlich groß und weist eine starke Abhängigkeit von STLSoft auf, was für die Verwendung in einigen Projekten möglicherweise zu restriktiv ist.
Dies ist keine Formatierungsbibliothek, aber der Vollständigkeit halber habe ich beschlossen, sie hier aufzunehmen. Als iostreams leidet es unter dem Problem, wörtlichen Text mit Argumenten zu vermischen. Die Bibliothek ist ziemlich schnell, aber langsamer bei der Ganzzahlformatierung als fmt::format_to
mit der Kompilierung von Formatzeichenfolgen auf Karmas eigenem Benchmark, siehe Konvertieren von hundert Millionen Ganzzahlen in Zeichenfolgen pro Sekunde.
{fmt} wird unter der MIT-Lizenz vertrieben.
Der Abschnitt zur Format-String-Syntax in der Dokumentation basiert auf dem Abschnitt aus der Dokumentation zum Python-String-Modul. Aus diesem Grund wird die Dokumentation unter der Python Software Foundation-Lizenz vertrieben, die in doc/python-license.txt verfügbar ist. Dies gilt nur, wenn Sie die Dokumentation von {fmt} verteilen.
Die {fmt}-Bibliothek wird von Victor Zverovich (vitaut) mit Beiträgen vieler anderer Personen gepflegt. Einige der Namen finden Sie unter Mitwirkende und Veröffentlichungen. Teilen Sie uns mit, wenn Ihr Beitrag nicht aufgeführt oder falsch erwähnt ist, und wir werden ihn korrigieren.
Um ein Sicherheitsproblem zu melden, geben Sie es bitte im Sicherheitshinweis an.
Dieses Projekt wird von einem Team von Freiwilligen mit angemessenem Aufwand betreut. Bitte geben Sie uns daher mindestens 90 Tage Zeit, um an einer Lösung zu arbeiten, bevor das Problem öffentlich bekannt gegeben wird.