Namensräume
Varianten
Aktionen

Standardformatierungsspezifikation (seit C++20)

Von cppreference.com
< cpp‎ | utility‎ | format
 
 
 
 

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
    n
    2
    Zeichen vor und
    n
    2
    Zeichen nach dem formatierten Argument eingefügt werden.

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, 0 oder 0x) 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 g und G Konvertierungen 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_Width den 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 bool verwendet 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.
  • ?: Kopiert die maskierte Zeichenkette (siehe unten) 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 ist 0b.
  • B: identisch mit b, außer dass das Basispräfix 0B ist.
  • c: Kopiert das Zeichen static_cast<CharT>(value) in die Ausgabe, wobei CharT der Zeichetyp der Formatierungszeichenkette ist. Löst std::format_error aus, wenn value nicht im Bereich der darstellbaren Werte für CharT liegt.
  • 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 ist 0, 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 ist 0x.
  • X: identisch mit x, außer dass es Großbuchstaben für Ziffern über 9 verwendet und das Basispräfix 0X ist.
  • 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.
  • ?: Kopiert das maskierte Zeichen (siehe unten) in die Ausgabe.
(seit C++23)

Die verfügbaren Präsentationstypen für bool sind:

  • none, s: Kopiert die textuelle Darstellung (true oder false, 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 mit a, außer dass es Großbuchstaben zur Darstellung von Ziffern über 9 verwendet und P zur 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 mit e, außer dass es E zur 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 mit g, außer dass es E zur 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äfix 0x, das der Ausgabe hinzugefügt wird; andernfalls ist die Ausgabe implementierungsabhängig.
  • P: identisch mit p, außer dass es Großbuchstaben für Ziffern über 9 verwendet und das Basispräfix 0X ist.
(seit C++26)


Formatierung von Maskierungszeichen und Zeichenketten

Ein 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:

  • Für jede wohlgeformte Code-Einheiten-Sequenz, die ein Zeichen C kodiert:
  • Wenn C eines der Zeichen in der folgenden Tabelle ist, wird die entsprechende Maskierungssequenz verwendet.
Zeichen Maskierungssequenz Anmerkungen
horizontales Tabulatorzeichen (Byte 0x09 in ASCII-Kodierung) \t
Zeilenvorschub - neue Zeile (Byte 0x0a in ASCII-Kodierung) \n
Wagenrücklauf (Byte 0x0d in ASCII-Kodierung) \r
doppelte Anführungszeichen (Byte 0x22 in ASCII-Kodierung) \" Wird nur verwendet, wenn die Ausgabe eine doppelt-geklammerte Zeichenkette ist.
einfache Anführungszeichen (Byte 0x27 in ASCII-Kodierung) \' Wird nur verwendet, wenn die Ausgabe eine einfach-geklammerte Zeichenkette ist.
Backslash (Byte 0x5c in ASCII-Kodierung) \\
  • Andernfalls, wenn C nicht das Leerzeichen ist (Byte 0x20 in ASCII-Kodierung) und entweder
  • die zugehörige Zeichenkodierung eine Unicode-Kodierung ist und
  • C einem Unicode-Skalarwert entspricht, dessen Unicode-Eigenschaft General_Category den Wert in den Gruppen Separator (Z) oder Other (C) hat, oder
  • C nicht unmittelbar von einem nicht maskierten Zeichen gefolgt wird und C einem Unicode-Skalarwert entspricht, der die Unicode-Eigenschaft Grapheme_Extend=Yes hat, oder
  • die zugehörige Zeichenkodierung keine Unicode-Kodierung ist und C zu einer implementierungsdefinierten Menge von Trenn- oder nicht druckbaren Zeichen gehört
ist die Maskierungssequenz \u{Hexadezimalziffernsequenz}, wobei Hexadezimalziffernsequenz die kürzeste hexadezimale Darstellung von C mit Kleinbuchstaben-Hexadezimalziffern ist.
  • Andernfalls wird C unverändert kopiert.
  • Eine Code-Einheiten-Sequenz, die eine Umschaltsequenz ist, hat unbestimmte Auswirkungen auf die Ausgabe und die weitere Dekodierung der Zeichenkette.
  • Andere Code-Einheiten (d.h. solche in nicht wohlgeformten Code-Einheiten-Sequenzen) werden jeweils durch \x{Hexadezimalziffernsequenz} ersetzt, wobei Hexadezimalziffernsequenz die kürzeste hexadezimale Darstellung der Code-Einheit mit Kleinbuchstaben-Hexadezimalziffern ist.

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.

Compiler Explorer Demo:

#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