Standard format specification (since C++20)
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 ⌊
⌋ caracteres antes y ⌈n 2
⌉ caracteres después del argumento formateado.n 2
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, o0x) 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
gyG, 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_Widthtenga 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.
|
(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 es0b. -
B: igual queb, excepto que el prefijo de base es0B. -
c: Copia el carácter static_cast < CharT > ( value ) a la salida, dondeCharTes 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 paraCharT. -
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 es0si 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 es0x. -
X: igual quex, excepto que utiliza letras mayúsculas para dígitos superiores a 9 y el prefijo de base es0X. -
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.
|
(desde C++23) |
Los tipos de presentación bool disponibles son:
-
ninguno,
s: Copia la representación textual (trueofalse, 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 quea, excepto que utiliza letras mayúsculas para dígitos superiores a 9 y usaPpara 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 quee, excepto que utilizaEpara 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 queg, excepto que utilizaEpara 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 prefijo0xañadido a la salida; de lo contrario, la salida está definida por la implementación.
|
(desde C++26) |
Formateo de caracteres y cadenas escapadosUn 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:
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 :
Ejecutar este código
#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 |