Namespaces
Variants

Standard format specification (since C++20)

From cppreference.net

Para tipos básicos y tipos de cadena, la especificación de formato se basa en la especificación de formato en Python .

La sintaxis de las especificaciones de formato es:

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

La opción de signo , # y 0 solo son válidas cuando se utiliza un tipo de presentación entero o de punto flotante.

Contenidos

Relleno y alineación

fill-and-align es un carácter de relleno opcional (que puede ser cualquier carácter excepto { o } ), seguido por una de las opciones de alineación < , > , ^ .

Si no se especifica ningún carácter de relleno, por defecto será el carácter de espacio. Para una especificación de formato en una codificación Unicode, el carácter de relleno debe corresponder a un único valor escalar Unicode.

El significado de las opciones de align es el siguiente:

  • < : Fuerza que el argumento formateado se alinee al inicio del espacio disponible insertando n caracteres de relleno después del argumento formateado. Esta es la opción predeterminada cuando se utiliza un tipo de presentación que no es entero ni de punto flotante.
  • > : Fuerza que el argumento formateado se alinee al final del espacio disponible insertando n caracteres de relleno antes del argumento formateado. Esta es la opción predeterminada cuando se utiliza un tipo de presentación entero o de punto flotante.
  • ^ : Fuerza que el argumento formateado se centre dentro del espacio disponible insertando
    n
    2
    caracteres antes y
    n
    2
    caracteres después del argumento formateado.

En cada caso, n es la diferencia entre el ancho mínimo del campo (especificado por width ) y el ancho estimado del argumento formateado, o 0 si la diferencia es menor que 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  ");
}

Signo, #, y 0

La sign opción puede ser una de las siguientes:

  • + : Indica que se debe utilizar un signo tanto para números no negativos como negativos. El + signo se inserta antes del valor de salida para números no negativos.
  • - : Indica que se debe utilizar un signo solo para números negativos (este es el comportamiento predeterminado).
  • espacio: Indica que se debe utilizar un espacio inicial para números no negativos, y un signo menos para números negativos.

El cero negativo se trata como un número negativo.

La opción de signo se aplica al infinito de punto flotante y 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");
}

La # opción hace que se utilice la forma alternativa para la conversión.

  • Para tipos integrales, cuando se utiliza la presentación binaria, octal o hexadecimal, la forma alternativa inserta el prefijo ( 0b , 0 , o 0x ) en el valor de salida después del carácter de signo (posiblemente espacio) si hay uno, o lo agrega antes del valor de salida en caso contrario.
  • Para tipos de punto flotante, la forma alternativa hace que el resultado de la conversión de valores finitos siempre contenga un carácter de punto decimal, incluso si no le siguen dígitos. Normalmente, un carácter de punto decimal aparece en el resultado de estas conversiones solo si le sigue un dígito. Además, para conversiones g y G , los ceros finales no se eliminan del resultado.

La opción 0 rellena el campo con ceros a la izquierda (después de cualquier indicación de signo o base) hasta el ancho del campo, excepto cuando se aplica a un infinito o NaN. Si el carácter 0 y una opción de align aparecen simultáneamente, el carácter 0 se ignora.

#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   "); // el 0 se ignora debido a '<'
}

Ancho y precisión

width es un número decimal positivo, o un campo de reemplazo anidado ( {} o { n } ). Si está presente, especifica el ancho mínimo del campo.

precision es un punto ( . ) seguido de un número decimal no negativo o un campo de reemplazo anidado. Este campo indica la precisión o el tamaño máximo del campo. Solo puede utilizarse con tipos de punto flotante y cadenas de texto.

  • Para tipos de punto flotante, este campo especifica la precisión de formato.
  • Para tipos de cadena, proporciona un límite superior para el ancho estimado (ver abajo ) del prefijo de la cadena que se copiará a la salida. Para una cadena en codificación Unicode, el texto que se copiará a la salida es el prefijo más largo de clústeres de grafemas extendidos completos cuyo ancho estimado no sea mayor que la precisión.

Si se utiliza un campo de reemplazo anidado para width o precision , y el argumento correspondiente no es de integral type (until C++23) standard signed or unsigned integer type (since C++23) , o es negativo, se lanza una excepción de tipo std::format_error .

float pi = 3.14f;
assert(std::format("{:10f}", pi)           == "  3.140000"); // ancho = 10
assert(std::format("{:{}f}", pi, 10)       == "  3.140000"); // ancho = 10
assert(std::format("{:.5f}", pi)           == "3.14000");    // precisión = 5
assert(std::format("{:.{}f}", pi, 5)       == "3.14000");    // precisión = 5
assert(std::format("{:10.5f}", pi)         == "   3.14000"); // ancho = 10, precisión = 5
assert(std::format("{:{}.{}f}", pi, 10, 5) == "   3.14000"); // ancho = 10, precisión = 5
auto b1 = std::format("{:{}f}", pi, 10.0); // lanza excepción: el ancho no es de tipo integral
auto b2 = std::format("{:{}f}", pi, -10);  // lanza excepción: el ancho es negativo
auto b3 = std::format("{:.{}f}", pi, 5.0); // lanza excepción: la precisión no es de tipo integral

El ancho de una cadena se define como el número estimado de posiciones de columna apropiadas para mostrarla en una terminal.

Para el propósito del cálculo de ancho, se asume que una cadena está en una codificación definida por la implementación. El método de cálculo de ancho no está especificado, pero para una cadena en codificación Unicode, la implementación debería estimar el ancho de la cadena como la suma de los anchos estimados de los primeros code points en sus extended grapheme clusters . El ancho estimado es 2 para los siguientes code points, y es 1 en caso contrario:

  • Cualquier punto de código cuya propiedad Unicode East_Asian_Width tenga el valor Fullwidth ( F ) o Wide ( W )
  • U+4DC0 - U+4DFF (Símbolos Hexagramas del Yijing)
  • U+1F300 – U+1F5FF (Símbolos Misceláneos y Pictografías)
  • U+1F900 – U+1F9FF (Símbolos y Pictografías Suplementarios)
#include <cassert>
#include <format>
int main()
{
    assert(std::format("{:.^5s}",   "🐱")    == ".🐱..");
    assert(std::format("{:.5s}",    "🐱🐱🐱") == "🐱🐱");
    assert(std::format("{:.<5.5s}", "🐱🐱🐱") == "🐱🐱.");
}

L (formato específico de la configuración regional)

La opción L hace que se utilice el formato específico de la configuración regional. Esta opción solo es válida para tipos aritméticos.

  • Para tipos integrales, la forma específica de la configuración regional inserta los caracteres separadores de grupos de dígitos apropiados según la configuración regional del contexto.
  • Para tipos de punto flotante, la forma específica de la configuración regional inserta los caracteres separadores de grupos de dígitos y separadores de base apropiados según la configuración regional del contexto.
  • Para la representación textual de bool , la forma específica de la configuración regional utiliza la cadena apropiada como si se obtuviera con std::numpunct::truename o std::numpunct::falsename .

Tipo

La type opción determina cómo deben presentarse los datos.

Los tipos de presentación de cadena disponibles son:

  • ninguno, s : Copia la cadena a la salida.
  • ? : Copia la cadena escapada (ver abajo ) a la salida.
(desde C++23)

Los tipos de presentación de enteros disponibles para tipos integrales distintos de char , wchar_t , y bool son:

  • b : Formato binario. Produce la salida como si se llamara a std:: to_chars ( first, last, value, 2 ) . El prefijo de base es 0b .
  • B : igual que b , excepto que el prefijo de base es 0B .
  • c : Copia el carácter static_cast < CharT > ( value ) a la salida, donde CharT es el tipo de carácter de la cadena de formato. Lanza std::format_error si el valor no está en el rango de valores representables para CharT .
  • d : Formato decimal. Produce la salida como si se llamara a std:: to_chars ( first, last, value ) .
  • o : Formato octal. Produce la salida como si se llamara a std:: to_chars ( first, last, value, 8 ) . El prefijo de base es 0 si el valor del argumento correspondiente es distinto de cero y está vacío en caso contrario.
  • x : Formato hexadecimal. Produce la salida como si se llamara a std:: to_chars ( first, last, value, 16 ) . El prefijo de base es 0x .
  • X : igual que x , excepto que utiliza letras mayúsculas para dígitos superiores a 9 y el prefijo de base es 0X .
  • ninguno: igual que d .

Los tipos de presentación disponibles para char y wchar_t son:

  • ninguno, c : Copia el carácter a la salida.
  • b , B , d , o , x , X : Utiliza tipos de presentación enteros con el valor static_cast < unsigned char > ( value ) o static_cast < std:: make_unsigned_t < wchar_t >> ( value ) respectivamente.
  • ? : Copia el carácter escapado (ver abajo ) a la salida.
(desde C++23)

Los tipos de presentación bool disponibles son:

  • ninguno, s : Copia la representación textual ( true o false , o la forma específica del locale) a la salida.
  • b , B , d , o , x , X : Utiliza tipos de presentación entera con el valor static_cast < unsigned char > ( value ) .

Los tipos de presentación de punto flotante disponibles son:

  • a : Si se especifica precisión , produce la salida como si se llamara a std:: to_chars ( first, last, value, std :: chars_format :: hex , precision ) donde precision es la precisión especificada; de lo contrario, la salida se produce como si se llamara a std:: to_chars ( first, last, value, std :: chars_format :: hex ) .
  • A : igual que a , excepto que utiliza letras mayúsculas para dígitos superiores a 9 y usa P para indicar el exponente.
  • e : Produce la salida como si se llamara a std:: to_chars ( first, last, value, std :: chars_format :: scientific , precision ) donde precision es la precisión especificada, o 6 si no se especifica precisión.
  • E : igual que e , excepto que utiliza E para indicar el exponente.
  • f , F : Produce la salida como si se llamara a std:: to_chars ( first, last, value, std :: chars_format :: fixed , precision ) donde precision es la precisión especificada, o 6 si no se especifica precisión.
  • g : Produce la salida como si se llamara a std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) donde precision es la precisión especificada, o 6 si no se especifica precisión.
  • G : igual que g , excepto que utiliza E para indicar el exponente.
  • ninguno: Si se especifica precisión , produce la salida como si se llamara a std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) donde precision es la precisión especificada; de lo contrario, la salida se produce como si se llamara a std:: to_chars ( first, last, value ) .

Para los tipos de presentación en minúsculas, infinito y NaN se formatean como inf y nan , respectivamente. Para los tipos de presentación en mayúsculas, infinito y NaN se formatean como INF y NAN , respectivamente.

std::format especificador std::chars_format especificador correspondiente de std::printf
a , A std::chars_format::hex a , A (pero std::format no genera el prefijo 0x o 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
ninguno std::chars_format::general si se especifica precisión, de lo contrario el formato de ida y vuelta más corto g si se especifica precisión. De lo contrario no hay especificador correspondiente.

Los tipos de presentación de puntero disponibles (también utilizados para std::nullptr_t ) son:

  • none, p : Si std::uintptr_t está definido, produce la salida como si se llamara a std:: to_chars ( first, last, reinterpret_cast < std:: uintptr_t > ( value ) , 16 ) con el prefijo 0x añadido a la salida; de lo contrario, la salida está definida por la implementación.
  • P : igual que p , excepto que utiliza letras mayúsculas para dígitos superiores a 9 y el prefijo de base es 0X .
(desde C++26)


Formateo de caracteres y cadenas escapados

Un carácter o cadena puede formatearse como escapado para hacerlo más adecuado para depuración o registro.

El escape se realiza de la siguiente manera:

  • Para cada secuencia de unidades de código bien formada que codifica un carácter C :
  • Si C es uno de los caracteres en la siguiente tabla, se utiliza la secuencia de escape correspondiente.
Carácter Secuencia de escape Notas
tabulación horizontal (byte 0x09 en codificación ASCII) \t
salto de línea - nueva línea (byte 0x0a en codificación ASCII) \n
retorno de carro (byte 0x0d en codificación ASCII) \r
comilla doble (byte 0x22 en codificación ASCII) \" Se usa solo si la salida es una cadena entre comillas dobles
comilla simple (byte 0x27 en codificación ASCII) \' Se usa solo si la salida es una cadena entre comillas simples
barra invertida (byte 0x5c en codificación ASCII) \\
  • En caso contrario, si C no es el carácter de espacio (byte 0x20 en codificación ASCII), y ya sea
  • la codificación de caracteres asociada es una codificación Unicode y
  • C corresponde a un valor escalar Unicode cuya propiedad Unicode General_Category tiene un valor en los grupos Separator ( Z ) o Other ( C ), o
  • C no está inmediatamente precedido por un carácter no escapado, y C corresponde a un valor escalar Unicode que tiene la propiedad Unicode Grapheme_Extend=Yes , o
  • la codificación de caracteres asociada no es una codificación Unicode y C es uno de un conjunto definido por la implementación de caracteres separadores o no imprimibles
la secuencia de escape es \u{ hex-digit-sequence } , donde hex-digit-sequence es la representación hexadecimal más corta de C usando dígitos hexadecimales en minúsculas.
  • En caso contrario, C se copia tal cual.
  • Una secuencia de unidades de código que es una secuencia de desplazamiento tiene un efecto no especificado en la salida y en la decodificación posterior de la cadena.
  • Otras unidades de código (es decir, aquellas en secuencias de unidades de código mal formadas) se reemplazan cada una con \x{ hex-digit-sequence } , donde hex-digit-sequence es la representación hexadecimal más corta de la unidad de código usando dígitos hexadecimales en minúsculas.

La representación de cadena escapada de una cadena se construye escapando las secuencias de unidades de código en la cadena, como se describió anteriormente, y citando el resultado con comillas dobles.

La representación escapada de un carácter se construye escapándolo como se describió anteriormente, y citando el resultado con comillas simples.

Demostración en Compiler Explorer :

#include <print>
int main()
{
    std::println("[{:?}]", "h\tllo");             // imprime: ["h\tllo"]
    std::println("[{:?}]", "Спасибо, Виктор ♥!"); // imprime: ["Спасибо, Виктор ♥!"]
    std::println("[{:?}] [{:?}]", '\'', '"');     // imprime: ['\'', '"']
    // Los siguientes ejemplos asumen el uso de la codificación UTF-8
    std::println("[{:?}]", std::string("\0 \n \t \x02 \x1b", 9));
                                             // imprime: ["\u{0} \n \t \u{2} \u{1b}"]
    std::println("[{:?}]", "\xc3\x28");      // UTF-8 inválido
                                             // imprime: ["\x{c3}("]
    std::println("[{:?}]", "\u0301");        // imprime: ["\u{301}"]
    std::println("[{:?}]", "\\\u0301");      // imprime: ["\\\u{301}"]
    std::println("[{:?}]", "e\u0301\u0323"); // imprime: ["ẹ́"]
}
(desde C++23)

Notas

En la mayoría de los casos la sintaxis es similar al antiguo % -formatting, con la adición de los {} y usando : en lugar de % . Por ejemplo, "%03.2f" puede traducirse a "{:03.2f}" .

Macro de prueba de características Valor Estándar Característica
__cpp_lib_format_uchar 202311L (C++20)
(DR)
Formateo de unidades de código como enteros sin signo

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Se aplica a Comportamiento publicado Comportamiento correcto
LWG 3721 C++20 no se permite cero para el campo de ancho
en la especificación de formato estándar
se permite cero si se especifica
mediante un campo de reemplazo
P2909R4 C++20 char o wchar_t podrían formatearse como
valores enteros sin signo fuera de rango
las unidades de código se convierten al tipo
sin signo correspondiente antes de dicho formateo