Standardformatierungsspezifikation (seit C++20)
Für Basistypen und Zeichentypen basiert die Formatierungsspezifikation auf der Formatierungsspezifikation in Python.
Die Syntax der Formatierungsspezifikationen lautet
Füllzeichen-und-Ausrichtung (optional) Vorzeichen (optional) #(optional) 0(optional) Breite (optional) Genauigkeit (optional) L(optional) Typ (optional) |
|||||||||
Die Optionen Vorzeichen, # und 0 sind nur gültig, wenn ein ganzzahliger oder Gleitkomma-Präsentationstyp verwendet wird.
Inhalt |
[bearbeiten] Füllzeichen und Ausrichtung
Füllzeichen-und-Ausrichtung ist ein optionales Füllzeichen (das jedes Zeichen außer { oder } sein kann), gefolgt von einer der Ausrichtungsoptionen <, >, ^.
Wenn kein Füllzeichen angegeben wird, wird standardmäßig das Leerzeichen verwendet. Für eine Formatierungsspezifikation in einer Unicode-Kodierung muss das Füllzeichen einem einzelnen Unicode-Skalarwert entsprechen.
Die Bedeutung der Ausrichtungsoptionen ist wie folgt:
-
<: Zwingt das formatierte Argument, am Anfang des verfügbaren Platzes ausgerichtet zu werden, indem n Füllzeichen nach dem formatierten Argument eingefügt werden. Dies ist der Standard, wenn ein Nicht-Ganzzahl-Nicht-Gleitkomma-Präsentationstyp verwendet wird. -
>: Zwingt das formatierte Argument, am Ende des verfügbaren Platzes ausgerichtet zu werden, indem n Füllzeichen vor dem formatierten Argument eingefügt werden. Dies ist der Standard, wenn ein Ganzzahl- oder Gleitkomma-Präsentationstyp verwendet wird. -
^: Zwingt das formatierte Argument, innerhalb des verfügbaren Platzes zentriert zu werden, indem ⌊
⌋ Zeichen vor und ⌈n 2
⌉ Zeichen nach dem formatierten Argument eingefügt werden.n 2
In jedem Fall ist n die Differenz zwischen der minimalen Feldbreite (angegeben durch Breite) und der geschätzten Breite des formatierten Arguments oder 0, wenn die Differenz kleiner als 0 ist.
#include <cassert> #include <format> int main() { char c = 120; assert(std::format("{:6}", 42) == " 42"); assert(std::format("{:6}", 'x') == "x "); assert(std::format("{:*<6}", 'x') == "x*****"); assert(std::format("{:*>6}", 'x') == "*****x"); assert(std::format("{:*^6}", 'x') == "**x***"); assert(std::format("{:6d}", c) == " 120"); assert(std::format("{:6}", true) == "true "); }
[bearbeiten] Vorzeichen, # und 0
Die Option Vorzeichen kann eine der folgenden sein:
-
+: Zeigt an, dass für positive und negative Zahlen ein Vorzeichen verwendet werden soll. Das+Zeichen wird vor dem Ausgabewert für nicht-negative Zahlen eingefügt. -
-: Zeigt an, dass ein Vorzeichen nur für negative Zahlen verwendet werden soll (dies ist das Standardverhalten). - Leerzeichen: Zeigt an, dass für nicht-negative Zahlen ein führendes Leerzeichen und für negative Zahlen ein Minuszeichen verwendet werden soll.
Negative Null wird als negative Zahl behandelt.
Die Option Vorzeichen gilt für Gleitkomma-Unendlichkeit und NaN.
#include <cassert> #include <format> #include <limits> int main() { double inf = std::numeric_limits<double>::infinity(); double nan = std::numeric_limits<double>::quiet_NaN(); assert(std::format("{0:},{0:+},{0:-},{0: }", 1) == "1,+1,1, 1"); assert(std::format("{0:},{0:+},{0:-},{0: }", -1) == "-1,-1,-1,-1"); assert(std::format("{0:},{0:+},{0:-},{0: }", inf) == "inf,+inf,inf, inf"); assert(std::format("{0:},{0:+},{0:-},{0: }", nan) == "nan,+nan,nan, nan"); }
Die Option # bewirkt, dass die alternative Form für die Konvertierung verwendet wird.
- Für ganzzahlige Typen wird bei Verwendung von binären, oktalen oder hexadezimalen Darstellungstypen die alternative Form dem Ausgabewert nach dem Vorzeichenzeichen (möglicherweise Leerzeichen) das Präfix (
0b,0oder0x) einfügen, falls vorhanden, oder es davor hinzufügen. - Für Gleitkommatypen bewirkt die alternative Form, dass das Ergebnis der Konvertierung von endlichen Werten immer ein Dezimalpunktzeichen enthält, auch wenn keine Ziffern folgen. Normalerweise erscheint ein Dezimalpunktzeichen im Ergebnis dieser Konvertierungen nur, wenn eine Ziffer folgt. Zusätzlich werden bei
gundGKonvertierungen keine nachgestellten Nullen aus dem Ergebnis entfernt.
Die Option 0 füllt das Feld mit führenden Nullen (nach jeder Angabe von Vorzeichen oder Basis) auf die Feldbreite auf, außer wenn sie auf Unendlichkeit oder NaN angewendet wird. Wenn das Zeichen 0 und eine Ausrichtungsoption beide erscheinen, wird das Zeichen 0 ignoriert.
#include <cassert> #include <format> int main() { char c = 120; assert(std::format("{:+06d}", c) == "+00120"); assert(std::format("{:#06x}", 0xa) == "0x000a"); assert(std::format("{:<06}", -42) == "-42 "); // 0 is ignored because of '<' }
[bearbeiten] Breite und Genauigkeit
Breite ist entweder eine positive Dezimalzahl oder ein verschachteltes Ersetzungsfeld ({} oder {n}). Wenn vorhanden, gibt sie die minimale Feldbreite an.
Genauigkeit ist ein Punkt (.), gefolgt von entweder einer nicht-negativen Dezimalzahl oder einem verschachtelten Ersetzungsfeld. Dieses Feld gibt die Genauigkeit oder die maximale Feldgröße an. Es kann nur mit Gleitkomma- und Zeichentypen verwendet werden.
- Für Gleitkommatypen gibt dieses Feld die Formatierungsgenauigkeit an.
- Für Zeichentypen stellt es eine Obergrenze für die geschätzte Breite (siehe unten) des Präfixes der Zeichenkette dar, das in die Ausgabe kopiert werden soll. Für eine Zeichenkette in einer Unicode-Kodierung ist der zu kopierende Text das längste Präfix von ganzen erweiterten Graphemclustern, deren geschätzte Breite nicht größer als die Genauigkeit ist.
Wenn ein verschachteltes Ersetzungsfeld für Breite oder Genauigkeit verwendet wird und das entsprechende Argument nicht vom Typ Integral(bis C++23)Standard signed or unsigned integer type(seit C++23) ist oder negativ ist, wird eine Ausnahme vom Typ std::format_error ausgelöst.
float pi = 3.14f; assert(std::format("{:10f}", pi) == " 3.140000"); // width = 10 assert(std::format("{:{}f}", pi, 10) == " 3.140000"); // width = 10 assert(std::format("{:.5f}", pi) == "3.14000"); // precision = 5 assert(std::format("{:.{}f}", pi, 5) == "3.14000"); // precision = 5 assert(std::format("{:10.5f}", pi) == " 3.14000"); // width = 10, precision = 5 assert(std::format("{:{}.{}f}", pi, 10, 5) == " 3.14000"); // width = 10, precision = 5 auto b1 = std::format("{:{}f}", pi, 10.0); // throws: width is not of integral type auto b2 = std::format("{:{}f}", pi, -10); // throws: width is negative auto b3 = std::format("{:.{}f}", pi, 5.0); // throws: precision is not of integral type
Die Breite einer Zeichenkette wird als die geschätzte Anzahl von Spaltenpositionen definiert, die für die Anzeige in einem Terminal geeignet sind.
Für die Breitenberechnung wird angenommen, dass eine Zeichenkette in einer implementierungsdefinierten Kodierung vorliegt. Die Methode der Breitenberechnung ist nicht spezifiziert, aber für eine Zeichenkette in einer Unicode-Kodierung sollten Implementierungen die Breite der Zeichenkette als Summe der geschätzten Breiten der ersten Codepunkte ihrer erweiterten Graphemcluster abschätzen. Die geschätzte Breite ist 2 für die folgenden Codepunkte und 1 sonst
- Jeder Codepunkt, dessen Unicode-Eigenschaft
East_Asian_Widthden Wert Fullwidth (F) oder Wide (W) hat - U+4DC0 - U+4DFF (Yijing Hexagramm-Symbole)
- U+1F300 – U+1F5FF (Miscellaneous Symbols and Pictographs)
- U+1F900 – U+1F9FF (Supplemental Symbols and Pictographs)
#include <cassert> #include <format> int main() { assert(std::format("{:.^5s}", "🐱") == ".🐱.."); assert(std::format("{:.5s}", "🐱🐱🐱") == "🐱🐱"); assert(std::format("{:.<5.5s}", "🐱🐱🐱") == "🐱🐱."); }
[bearbeiten] L (lokalisierungsabhängige Formatierung)
Die Option L bewirkt, dass die lokalenspezifische Form verwendet wird. Diese Option ist nur für arithmetische Typen gültig.
- Für ganzzahlige Typen fügt die lokalenspezifische Form die entsprechenden Zifferngruppentrennzeichen gemäß dem Gebietsschema des Kontexts ein.
- Für Gleitkommatypen fügt die lokalenspezifische Form die entsprechenden Zifferngruppen- und Radix-Trennzeichen gemäß dem Gebietsschema des Kontexts ein.
- Für die textuelle Darstellung von
boolverwendet die lokalenspezifische Form die entsprechende Zeichenkette, als ob sie mit std::numpunct::truename oder std::numpunct::falsename erhalten worden wäre.
[bearbeiten] Typ
Die Option Typ bestimmt, wie die Daten dargestellt werden sollen.
Die verfügbaren Zeichenketten-Präsentationstypen sind:
- none,
s: Kopiert die Zeichenkette in die Ausgabe.
|
(seit C++23) |
Die verfügbaren Ganzzahl-Präsentationstypen für ganzzahlige Typen außer char, wchar_t und bool sind:
-
b: Binärformat. Erzeugt die Ausgabe, als ob std::to_chars(first, last, value, 2) aufgerufen worden wäre. Das Basispräfix ist0b. -
B: identisch mitb, außer dass das Basispräfix0Bist. -
c: Kopiert das Zeichen static_cast<CharT>(value) in die Ausgabe, wobeiCharTder Zeichetyp der Formatierungszeichenkette ist. Löst std::format_error aus, wennvaluenicht im Bereich der darstellbaren Werte fürCharTliegt. -
d: Dezimalformat. Erzeugt die Ausgabe, als ob std::to_chars(first, last, value) aufgerufen worden wäre. -
o: Oktalformat. Erzeugt die Ausgabe, als ob std::to_chars(first, last, value, 8) aufgerufen worden wäre. Das Basispräfix ist0, wenn der entsprechende Argumentwert ungleich Null ist, und sonst leer. -
x: Hexadezimalformat. Erzeugt die Ausgabe, als ob std::to_chars(first, last, value, 16) aufgerufen worden wäre. Das Basispräfix ist0x. -
X: identisch mitx, außer dass es Großbuchstaben für Ziffern über 9 verwendet und das Basispräfix0Xist. - none: identisch mit
d.
Die verfügbaren Präsentationstypen für char und wchar_t sind:
- none,
c: Kopiert das Zeichen in die Ausgabe. -
b,B,d,o,x,X: Verwendet Ganzzahl-Präsentationstypen mit dem Wert static_cast<unsigned char>(value) oder static_cast<std::make_unsigned_t<wchar_t>>(value) entsprechend.
|
(seit C++23) |
Die verfügbaren Präsentationstypen für bool sind:
- none,
s: Kopiert die textuelle Darstellung (trueoderfalse, oder die lokalenspezifische Form) in die Ausgabe. -
b,B,d,o,x,X: Verwendet Ganzzahl-Präsentationstypen mit dem Wert static_cast<unsigned char>(value).
Die verfügbaren Gleitkomma-Präsentationstypen sind:
-
a: Wenn Genauigkeit angegeben ist, wird die Ausgabe erzeugt, als ob std::to_chars(first, last, value, std::chars_format::hex, precision) aufgerufen worden wäre, wobei precision die angegebene Genauigkeit ist; andernfalls wird die Ausgabe erzeugt, als ob std::to_chars(first, last, value, std::chars_format::hex) aufgerufen worden wäre. -
A: identisch mita, außer dass es Großbuchstaben zur Darstellung von Ziffern über 9 verwendet undPzur Angabe des Exponenten verwendet. -
e: Erzeugt die Ausgabe, als ob std::to_chars(first, last, value, std::chars_format::scientific, precision) aufgerufen worden wäre, wobei precision die angegebene Genauigkeit ist oder 6, wenn keine Genauigkeit angegeben ist. -
E: identisch mite, außer dass esEzur Angabe des Exponenten verwendet. -
f,F: Erzeugt die Ausgabe, als ob std::to_chars(first, last, value, std::chars_format::fixed, precision) aufgerufen worden wäre, wobei precision die angegebene Genauigkeit ist oder 6, wenn keine Genauigkeit angegeben ist. -
g: Erzeugt die Ausgabe, als ob std::to_chars(first, last, value, std::chars_format::general, precision) aufgerufen worden wäre, wobei precision die angegebene Genauigkeit ist oder 6, wenn keine Genauigkeit angegeben ist. -
G: identisch mitg, außer dass esEzur Angabe des Exponenten verwendet. - none: Wenn Genauigkeit angegeben ist, wird die Ausgabe erzeugt, als ob std::to_chars(first, last, value, std::chars_format::general, precision) aufgerufen worden wäre, wobei precision die angegebene Genauigkeit ist; andernfalls wird die Ausgabe erzeugt, als ob std::to_chars(first, last, value) aufgerufen worden wäre.
Für Kleinbuchstaben-Präsentationstypen werden Unendlichkeit und NaN als inf bzw. nan formatiert. Für Großbuchstaben-Präsentationstypen werden Unendlichkeit und NaN als INF bzw. NAN formatiert.
Die verfügbaren Zeiger-Präsentationstypen (auch für std::nullptr_t) sind:
- none,
p: Wenn std::uintptr_t definiert ist, wird die Ausgabe erzeugt, als ob std::to_chars(first, last, reinterpret_cast<std::uintptr_t>(value), 16) mit dem Präfix0x, das der Ausgabe hinzugefügt wird; andernfalls ist die Ausgabe implementierungsabhängig.
|
(seit C++26) |
Formatierung von Maskierungszeichen und ZeichenkettenEin Zeichen oder eine Zeichenkette kann maskiert formatiert werden, um es für Debugging- oder Logging-Zwecke besser geeignet zu machen. Die Maskierung erfolgt wie folgt:
Die maskierte Zeichenketten-Darstellung einer Zeichenkette wird konstruiert, indem die Code-Einheiten-Sequenzen in der Zeichenkette wie oben beschrieben maskiert und das Ergebnis mit doppelten Anführungszeichen eingeschlossen wird. Die maskierte Darstellung eines Zeichens wird konstruiert, indem es wie oben beschrieben maskiert und das Ergebnis mit einfachen Anführungszeichen eingeschlossen wird. Führen Sie diesen Code aus #include <print> int main() { std::println("[{:?}]", "h\tllo"); // prints: ["h\tllo"] std::println("[{:?}]", "Спасибо, Виктор ♥!"); // prints: ["Спасибо, Виктор ♥!"] std::println("[{:?}] [{:?}]", '\'', '"'); // prints: ['\'', '"'] // The following examples assume use of the UTF-8 encoding std::println("[{:?}]", std::string("\0 \n \t \x02 \x1b", 9)); // prints: ["\u{0} \n \t \u{2} \u{1b}"] std::println("[{:?}]", "\xc3\x28"); // invalid UTF-8 // prints: ["\x{c3}("] std::println("[{:?}]", "\u0301"); // prints: ["\u{301}"] std::println("[{:?}]", "\\\u0301"); // prints: ["\\\u{301}"] std::println("[{:?}]", "e\u0301\u0323"); // prints: ["ẹ́"] } |
(seit C++23) |
[bearbeiten] Hinweise
In den meisten Fällen ist die Syntax ähnlich der alten %-Formatierung, mit der Ergänzung von {} und der Verwendung von : anstelle von %. Zum Beispiel kann "%03.2f" zu "{:03.2f}" übersetzt werden.
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_format_uchar |
202311L |
(C++20) (DR) |
Formatierung von Code-Einheiten als vorzeichenlose Ganzzahlen |
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 3721 | C++20 | Null ist für das Breitenfeld nicht zulässig in Standardformatierungsspezifikationen |
Null ist zulässig, wenn angegeben über ein Ersetzungsfeld |
| P2909R4 | C++20 | char oder wchar_t könnten formatiert werden als außerhalb des Bereichs liegende vorzeichenlose Ganzzahlwerte |
Code-Einheiten werden konvertiert in die entsprechende vorzeichenlose Zahl vor einer solchen Formatierung |