Namespaces
Variants

Standard format specification (since C++20)

From cppreference.net

Pour les types de base et les types chaîne, la spécification de format est basée sur la spécification de format en Python .

La syntaxe des spécifications de format est :

fill-and-align  (optionnel) sign  (optionnel) # (optionnel) 0 (optionnel) width  (optionnel) precision  (optionnel) L (optionnel) type  (optionnel)

Les options signe , # et 0 ne sont valides que lorsqu'un type de présentation entier ou à virgule flottante est utilisé.

Table des matières

Remplissage et alignement

fill-and-align est un caractère de remplissage optionnel (qui peut être n'importe quel caractère autre que { ou } ), suivi par l'une des options d' alignement < , > , ^ .

Si aucun caractère de remplissage n'est spécifié, il prend par défaut le caractère d'espace. Pour une spécification de format dans un encodage Unicode, le caractère de remplissage doit correspondre à une valeur scalaire Unicode unique.

La signification des options align est la suivante :

  • < : Force l'argument formaté à s'aligner au début de l'espace disponible en insérant n caractères de remplissage après l'argument formaté. Ceci est le comportement par défaut lorsqu'un type de présentation non entier et non flottant est utilisé.
  • > : Force l'argument formaté à s'aligner à la fin de l'espace disponible en insérant n caractères de remplissage avant l'argument formaté. Ceci est le comportement par défaut lorsqu'un type de présentation entier ou flottant est utilisé.
  • ^ : Force l'argument formaté à être centré dans l'espace disponible en insérant
    n
    2
    caractères avant et
    n
    2
    caractères après l'argument formaté.

Dans chaque cas, n représente la différence entre la largeur minimale du champ (spécifiée par width ) et la largeur estimée de l'argument formaté, ou 0 si la différence est inférieure à 0.

#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  ");
}

Signe, #, et 0

L'option sign peut être l'une des suivantes :

  • + : Indique qu'un signe doit être utilisé pour les nombres non négatifs et négatifs. Le signe + est inséré avant la valeur de sortie pour les nombres non négatifs.
  • - : Indique qu'un signe doit être utilisé uniquement pour les nombres négatifs (comportement par défaut).
  • espace : Indique qu'un espace initial doit être utilisé pour les nombres non négatifs, et un signe moins pour les nombres négatifs.

Le zéro négatif est traité comme un nombre négatif.

L'option de signe s'applique à l'infini et au NaN en virgule flottante.

#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");
}

L'option # provoque l'utilisation de la forme alternative pour la conversion.

  • Pour les types entiers, lorsque la présentation binaire, octale ou hexadécimale est utilisée, la forme alternative insère le préfixe ( 0b , 0 , ou 0x ) dans la valeur de sortie après le caractère de signe (éventuellement un espace) s'il y en a un, ou l'ajoute avant la valeur de sortie sinon.
  • Pour les types à virgule flottante, la forme alternative entraîne que le résultat de la conversion des valeurs finies contienne toujours un caractère de point décimal, même si aucun chiffre ne le suit. Normalement, un caractère de point décimal apparaît dans le résultat de ces conversions uniquement si un chiffre le suit. De plus, pour les conversions g et G , les zéros de fin ne sont pas supprimés du résultat.

L'option 0 remplit le champ avec des zéros non significatifs (après toute indication de signe ou de base) jusqu'à la largeur du champ, sauf lorsqu'elle est appliquée à un infini ou un NaN. Si le caractère 0 et une option d' alignement apparaissent tous deux, le caractère 0 est ignoré.

#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 est ignoré à cause de '<'
}

Largeur et précision

width est soit un nombre décimal positif, soit un champ de remplacement imbriqué ( {} ou { n } ). S'il est présent, il spécifie la largeur minimale du champ.

precision est un point ( . ) suivi soit d'un nombre décimal non négatif, soit d'un champ de remplacement imbriqué. Ce champ indique la précision ou la taille maximale du champ. Il ne peut être utilisé qu'avec les types à virgule flottante et les chaînes de caractères.

  • Pour les types à virgule flottante, ce champ spécifie la précision du formatage.
  • Pour les types chaîne de caractères, il fournit une limite supérieure pour la largeur estimée (voir ci-dessous ) du préfixe de la chaîne à copier vers la sortie. Pour une chaîne dans un encodage Unicode, le texte à copier vers la sortie est le préfixe le plus long de graphemes étendus complets dont la largeur estimée n'est pas supérieure à la précision.

Si un champ de remplacement imbriqué est utilisé pour width ou precision , et que l'argument correspondant n'est pas de integral type (until C++23) standard signed or unsigned integer type (since C++23) , ou est négatif, une exception de type std::format_error est levée.

float pi = 3.14f;
assert(std::format("{:10f}", pi)           == "  3.140000"); // largeur = 10
assert(std::format("{:{}f}", pi, 10)       == "  3.140000"); // largeur = 10
assert(std::format("{:.5f}", pi)           == "3.14000");    // précision = 5
assert(std::format("{:.{}f}", pi, 5)       == "3.14000");    // précision = 5
assert(std::format("{:10.5f}", pi)         == "   3.14000"); // largeur = 10, précision = 5
assert(std::format("{:{}.{}f}", pi, 10, 5) == "   3.14000"); // largeur = 10, précision = 5
auto b1 = std::format("{:{}f}", pi, 10.0); // lève une exception : la largeur n'est pas de type intégral
auto b2 = std::format("{:{}f}", pi, -10);  // lève une exception : la largeur est négative
auto b3 = std::format("{:.{}f}", pi, 5.0); // lève une exception : la précision n'est pas de type intégral

La largeur d'une chaîne est définie comme le nombre estimé de positions de colonnes appropriées pour l'afficher dans un terminal.

Pour le calcul de la largeur, une chaîne est supposée être dans un encodage défini par l'implémentation. La méthode de calcul de la largeur n'est pas spécifiée, mais pour une chaîne dans un encodage Unicode, l'implémentation doit estimer la largeur de la chaîne comme la somme des largeurs estimées des premiers points de code dans ses graphemes étendus . La largeur estimée est de 2 pour les points de code suivants, et de 1 autrement :

  • Tout point de code dont la propriété Unicode East_Asian_Width a la valeur Pleine largeur ( F ) ou Large ( W )
  • U+4DC0 - U+4DFF (Symboles des hexagrammes du Yijing)
  • U+1F300 – U+1F5FF (Symboles et pictogrammes divers)
  • U+1F900 – U+1F9FF (Symboles et pictogrammes supplémentaires)
#include <cassert>
#include <format>
int main()
{
    assert(std::format("{:.^5s}",   "🐱")    == ".🐱..");
    assert(std::format("{:.5s}",    "🐱🐱🐱") == "🐱🐱");
    assert(std::format("{:.<5.5s}", "🐱🐱🐱") == "🐱🐱.");
}

L (formatage spécifique aux paramètres régionaux)

L'option L entraîne l'utilisation de la forme spécifique aux paramètres régionaux. Cette option n'est valide que pour les types arithmétiques.

  • Pour les types entiers, la forme spécifique aux paramètres régionaux insère les caractères de séparation de groupes de chiffres appropriés selon les paramètres régionaux du contexte.
  • Pour les types à virgule flottante, la forme spécifique aux paramètres régionaux insère les caractères de séparation de groupes de chiffres et de séparation décimale appropriés selon les paramètres régionaux du contexte.
  • Pour la représentation textuelle de bool , la forme spécifique aux paramètres régionaux utilise la chaîne appropriée comme si elle était obtenue avec std::numpunct::truename ou std::numpunct::falsename .

Type

L'option type détermine comment les données doivent être présentées.

Les types de présentation de chaîne disponibles sont :

  • none, s : Copie la chaîne vers la sortie.
  • ? : Copie la chaîne échappée (voir ci-dessous ) vers la sortie.
(depuis C++23)

Les types de présentation entiers disponibles pour les types intégraux autres que char , wchar_t , et bool sont :

  • b : Format binaire. Produit la sortie comme en appelant std:: to_chars ( first, last, value, 2 ) . Le préfixe de base est 0b .
  • B : identique à b , sauf que le préfixe de base est 0B .
  • c : Copie le caractère static_cast < CharT > ( value ) vers la sortie, où CharT est le type de caractère de la chaîne de format. Lance std::format_error si la valeur n'est pas dans la plage des valeurs représentables pour CharT .
  • d : Format décimal. Produit la sortie comme en appelant std:: to_chars ( first, last, value ) .
  • o : Format octal. Produit la sortie comme en appelant std:: to_chars ( first, last, value, 8 ) . Le préfixe de base est 0 si la valeur d'argument correspondante est non nulle et est vide sinon.
  • x : Format hexadécimal. Produit la sortie comme en appelant std:: to_chars ( first, last, value, 16 ) . Le préfixe de base est 0x .
  • X : identique à x , sauf qu'il utilise des lettres majuscules pour les chiffres au-dessus de 9 et le préfixe de base est 0X .
  • aucun : identique à d .

Les types de présentation disponibles pour char et wchar_t sont :

  • none, c : Copie le caractère vers la sortie.
  • b , B , d , o , x , X : Utilise les types de présentation entiers avec la valeur static_cast < unsigned char > ( value ) ou static_cast < std:: make_unsigned_t < wchar_t >> ( value ) respectivement.
  • ? : Copie le caractère échappé (voir ci-dessous ) vers la sortie.
(depuis C++23)

Les types de présentation disponibles pour bool sont :

  • none, s : Copie la représentation textuelle ( true ou false , ou la forme spécifique à la locale) vers la sortie.
  • b , B , d , o , x , X : Utilise les types de présentation entière avec la valeur static_cast < unsigned char > ( value ) .

Les types de présentation en virgule flottante disponibles sont :

  • a : Si precision est spécifiée, produit le résultat comme en appelant std:: to_chars ( first, last, value, std :: chars_format :: hex , precision ) precision est la précision spécifiée ; sinon, le résultat est produit comme en appelant std:: to_chars ( first, last, value, std :: chars_format :: hex ) .
  • A : identique à a , sauf qu'il utilise des lettres majuscules pour les chiffres au-dessus de 9 et utilise P pour indiquer l'exposant.
  • e : Produit le résultat comme en appelant std:: to_chars ( first, last, value, std :: chars_format :: scientific , precision ) precision est la précision spécifiée, ou 6 si la précision n'est pas spécifiée.
  • E : identique à e , sauf qu'il utilise E pour indiquer l'exposant.
  • f , F : Produit le résultat comme en appelant std:: to_chars ( first, last, value, std :: chars_format :: fixed , precision ) precision est la précision spécifiée, ou 6 si la précision n'est pas spécifiée.
  • g : Produit le résultat comme en appelant std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) precision est la précision spécifiée, ou 6 si la précision n'est pas spécifiée.
  • G : identique à g , sauf qu'il utilise E pour indiquer l'exposant.
  • aucun : Si precision est spécifiée, produit le résultat comme en appelant std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) precision est la précision spécifiée ; sinon, le résultat est produit comme en appelant std:: to_chars ( first, last, value ) .

Pour les types de présentation en minuscules, l'infini et NaN sont formatés respectivement comme inf et nan . Pour les types de présentation en majuscules, l'infini et NaN sont formatés respectivement comme INF et NAN .

std::format spécificateur std::chars_format spécificateur std::printf correspondant
a , A std::chars_format::hex a , A (mais std::format ne génère pas les préfixes 0x ou 0X )
e , E std::chars_format::scientific e , E
f , F std::chars_format::fixed f , F
g , G std::chars_format::general g , G
aucun std::chars_format::general si la précision est spécifiée, sinon le format aller-retour le plus court g si la précision est spécifiée. Sinon il n'y a pas de spécificateur correspondant.

Les types de présentation de pointeur disponibles (également utilisés pour std::nullptr_t ) sont :

  • none, p : Si std::uintptr_t est défini, produit la sortie comme en appelant std:: to_chars ( first, last, reinterpret_cast < std:: uintptr_t > ( value ) , 16 ) avec le préfixe 0x ajouté à la sortie ; sinon, la sortie est définie par l'implémentation.
  • P : identique à p , sauf qu'il utilise des lettres majuscules pour les chiffres au-dessus de 9 et le préfixe de base est 0X .
(depuis C++26)


Formatage des caractères et chaînes échappés

Un caractère ou une chaîne peut être formaté comme échappé pour le rendre plus adapté au débogage ou à la journalisation.

L'échappement s'effectue comme suit :

  • Pour chaque séquence d'unités de code bien formée qui encode un caractère C :
  • Si C est l'un des caractères du tableau suivant, la séquence d'échappement correspondante est utilisée.
Caractère Séquence d'échappement Notes
tabulation horizontale (octet 0x09 en codage ASCII) \t
saut de ligne - nouvelle ligne (octet 0x0a en codage ASCII) \n
retour chariot (octet 0x0d en codage ASCII) \r
guillemet double (octet 0x22 en codage ASCII) \" Utilisé uniquement si la sortie est une chaîne entre guillemets doubles
guillemet simple (octet 0x27 en codage ASCII) \' Utilisé uniquement si la sortie est une chaîne entre guillemets simples
barre oblique inverse (octet 0x5c en codage ASCII) \\
  • Sinon, si C n'est pas le caractère espace (octet 0x20 en codage ASCII), et soit
  • l'encodage de caractères associé est un encodage Unicode et
  • C correspond à une valeur scalaire Unicode dont la propriété Unicode General_Category a une valeur dans les groupes Separator ( Z ) ou Other ( C ), ou
  • C n'est pas immédiatement précédé d'un caractère non échappé, et C correspond à une valeur scalaire Unicode qui a la propriété Unicode Grapheme_Extend=Yes , ou
  • l'encodage de caractères associé n'est pas un encodage Unicode et C fait partie d'un ensemble défini par l'implémentation de caractères séparateurs ou non imprimables
la séquence d'échappement est \u{ hex-digit-sequence } , où hex-digit-sequence est la représentation hexadécimale la plus courte de C utilisant des chiffres hexadécimaux en minuscules.
  • Sinon, C est copié tel quel.
  • Une séquence d'unités de code qui est une séquence de décalage a un effet non spécifié sur la sortie et le décodage ultérieur de la chaîne.
  • Les autres unités de code (c'est-à-dire celles dans des séquences d'unités de code mal formées) sont chacune remplacées par \x{ hex-digit-sequence } , où hex-digit-sequence est la représentation hexadécimale la plus courte de l'unité de code utilisant des chiffres hexadécimaux en minuscules.

La représentation échappée d'une chaîne est construite en échappant les séquences d'unités de code dans la chaîne, comme décrit ci-dessus, et en mettant le résultat entre guillemets doubles.

La représentation échappée d'un caractère est construite en l'échappant comme décrit ci-dessus, et en mettant le résultat entre guillemets simples.

Démo Compiler Explorer :

#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: ["ẹ́"]
}
(depuis C++23)

Notes

Dans la plupart des cas, la syntaxe est similaire à l'ancien formatage avec % , avec l'ajout des {} et en utilisant : à la place de % . Par exemple, "%03.2f" peut être traduit en "{:03.2f}" .

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_lib_format_uchar 202311L (C++20)
(DR)
Formatage des unités de code en tant qu'entiers non signés

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
LWG 3721 C++20 zéro n'est pas autorisé pour le champ de largeur
dans la spécification de format standard
zéro est permis s'il est spécifié
via un champ de remplacement
P2909R4 C++20 char ou wchar_t pourraient être formatés comme
valeurs entières non signées hors plage
les unités de code sont converties vers le type non signé
correspondant avant un tel formatage