Standard format specification (since C++20)
Для базовых типов и строковых типов спецификация формата основана на спецификации формата в Python .
Синтаксис спецификаций формата:
fill-and-align
(необязательно)
sign
(необязательно)
#
(необязательно)
0
(необязательно)
width
(необязательно)
precision
(необязательно)
L
(необязательно)
type
(необязательно)
|
|||||||||
Опции
sign
,
#
и
0
действительны только при использовании целочисленного или вещественного типа представления.
Содержание |
Заполнение и выравнивание
fill-and-align
— это необязательный
fill
символ (который может быть любым символом, кроме
{
или
}
), за которым следует одна из опций
align
<
,
>
,
^
.
Если символ заполнения не указан, по умолчанию используется пробел. Для спецификации формата в кодировке Unicode символ заполнения должен соответствовать одному скалярному значению Unicode.
Значение параметров align следующее:
-
<: Принудительно выравнивает форматируемый аргумент по началу доступного пространства, вставляя n символов заполнения после форматируемого аргумента. Это поведение по умолчанию при использовании нецелочисленного невещественного типа представления. -
>: Принудительно выравнивает форматируемый аргумент по концу доступного пространства, вставляя n символов заполнения перед форматируемым аргументом. Это поведение по умолчанию при использовании целочисленного или вещественного типа представления. -
^: Принудительно центрирует форматируемый аргумент в пределах доступного пространства, вставляя ⌊
⌋ символов перед и ⌈n 2
⌉ символов после форматируемого аргумента.n 2
В каждом случае, n представляет собой разницу между минимальной шириной поля (заданной параметром width ) и расчетной шириной форматированного аргумента, или 0, если разница меньше 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 "); }
Знак, # и 0
Опция sign может быть одним из следующих:
-
+: Указывает, что знак должен использоваться как для неотрицательных, так и для отрицательных чисел. Знак+вставляется перед выводом значения для неотрицательных чисел. -
-: Указывает, что знак должен использоваться только для отрицательных чисел (это поведение по умолчанию). - пробел: Указывает, что для неотрицательных чисел должен использоваться ведущий пробел, а для отрицательных - знак минус.
Отрицательный ноль трактуется как отрицательное число.
Опция sign применяется к бесконечности и 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"); }
Опция
#
приводит к использованию
альтернативной формы
для преобразования.
-
Для целочисленных типов, при использовании двоичного, восьмеричного или шестнадцатеричного формата представления, альтернативная форма вставляет префикс (
0b,0, или0x) в выводимое значение после знака (возможно, пробела), если он присутствует, или добавляет его перед выводимым значением в противном случае. -
Для типов с плавающей точкой, альтернативная форма приводит к тому, что результат преобразования конечных значений всегда содержит символ десятичной точки, даже если за ним не следует цифр. Обычно символ десятичной точки появляется в результате этих преобразований только если после него следует цифра. Кроме того, для преобразований
gиG, завершающие нули не удаляются из результата.
Опция
0
заполняет поле ведущими нулями (после любого указания знака или основания) до ширины поля, за исключением случаев применения к бесконечности или NaN. Если символ
0
и опция
align
присутствуют одновременно, символ
0
игнорируется.
#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 игнорируется из-за '<' }
Ширина и точность
width
представляет собой либо положительное десятичное число, либо вложенное поле замены (
{}
или
{
n
}
). Если присутствует, задает минимальную ширину поля.
precision
— это точка (
.
), за которой следует либо неотрицательное десятичное число, либо вложенное поле замены. Это поле указывает на точность или максимальный размер поля. Оно может использоваться только с типами с плавающей точкой и строковыми типами.
- Для типов с плавающей запятой это поле определяет точность форматирования.
- Для строковых типов оно задает верхнюю границу для предполагаемой ширины (см. ниже ) префикса строки, который будет скопирован в вывод. Для строк в Unicode-кодировке текст, копируемый в вывод, представляет собой самый длинный префикс из целых расширенных кластеров графем, предполагаемая ширина которого не превышает точность.
Если для width или precision используется вложенное поле замены, и соответствующий аргумент не является integral type (until C++23) standard signed or unsigned integer type (since C++23) , или является отрицательным, выбрасывается исключение типа std::format_error .
float pi = 3.14f; assert(std::format("{:10f}", pi) == " 3.140000"); // ширина = 10 assert(std::format("{:{}f}", pi, 10) == " 3.140000"); // ширина = 10 assert(std::format("{:.5f}", pi) == "3.14000"); // точность = 5 assert(std::format("{:.{}f}", pi, 5) == "3.14000"); // точность = 5 assert(std::format("{:10.5f}", pi) == " 3.14000"); // ширина = 10, точность = 5 assert(std::format("{:{}.{}f}", pi, 10, 5) == " 3.14000"); // ширина = 10, точность = 5 auto b1 = std::format("{:{}f}", pi, 10.0); // выбрасывает исключение: ширина не целочисленного типа auto b2 = std::format("{:{}f}", pi, -10); // выбрасывает исключение: ширина отрицательная auto b3 = std::format("{:.{}f}", pi, 5.0); // выбрасывает исключение: точность не целочисленного типа
Ширина строки определяется как предполагаемое количество позиций столбцов, подходящих для её отображения в терминале.
Для целей вычисления ширины предполагается, что строка находится в определяемой реализацией кодировке. Метод вычисления ширины не специфицирован, но для строки в Unicode-кодировке реализация должна оценивать ширину строки как сумму оценочных ширин первых кодовых точек в её расширенных кластерах графем . Оценочная ширина равна 2 для следующих кодовых точек, и равна 1 в остальных случаях:
-
Любой кодовый символ, чьё свойство Юникода
East_Asian_Widthимеет значение Fullwidth (F) или Wide (W) - U+4DC0 - U+4DFF (Символы гексаграмм И-Цзин)
- U+1F300 – U+1F5FF (Разнообразные символы и пиктограммы)
- U+1F900 – U+1F9FF (Дополнительные символы и пиктограммы)
#include <cassert> #include <format> int main() { assert(std::format("{:.^5s}", "🐱") == ".🐱.."); assert(std::format("{:.5s}", "🐱🐱🐱") == "🐱🐱"); assert(std::format("{:.<5.5s}", "🐱🐱🐱") == "🐱🐱."); }
L (форматирование с учетом локали)
Опция
L
приводит к использованию локализованной формы. Эта опция действительна только для арифметических типов.
- Для целочисленных типов локализованная форма вставляет соответствующие символы разделителей групп цифр в соответствии с локалью контекста.
- Для типов с плавающей точкой локализованная форма вставляет соответствующие символы разделителей групп цифр и десятичных разделителей в соответствии с локалью контекста.
-
Для текстового представления
bool, локализованная форма использует соответствующую строку, как если бы она была получена с помощью std::numpunct::truename или std::numpunct::falsename .
Тип
Опция type определяет, как данные должны быть представлены.
Доступные типы представления строки:
-
none,
s: Копирует строку в вывод.
|
(since C++23) |
Доступные целочисленные форматы представления для целочисленных типов, кроме char , wchar_t и bool :
-
b: Двоичный формат. Выводит результат так, как если бы вызывался std:: to_chars ( first, last, value, 2 ) . Префикс системы счисления:0b. -
B: аналогичноb, но префикс системы счисления:0B. -
c: Копирует символ static_cast < CharT > ( value ) в вывод, гдеCharT— символьный тип строки формата. Выбрасывает std::format_error , если значение не входит в диапазон представимых значений дляCharT. -
d: Десятичный формат. Выводит результат так, как если бы вызывался std:: to_chars ( first, last, value ) . -
o: Восьмеричный формат. Выводит результат так, как если бы вызывался std:: to_chars ( first, last, value, 8 ) . Префикс системы счисления:0, если соответствующее значение аргумента не равно нулю, и пустая строка в противном случае. -
x: Шестнадцатеричный формат. Выводит результат так, как если бы вызывался std:: to_chars ( first, last, value, 16 ) . Префикс системы счисления:0x. -
X: аналогичноx, но использует заглавные буквы для цифр выше 9 и префикс системы счисления:0X. -
отсутствует: аналогично
d.
Доступные char и wchar_t типы представления:
-
none,
c: Копирует символ в вывод. -
b,B,d,o,x,X: Использует целочисленные типы представления со значением static_cast < unsigned char > ( value ) или static_cast < std:: make_unsigned_t < wchar_t >> ( value ) соответственно.
|
(начиная с C++23) |
Доступные bool типы представления:
-
none,
s: Копирует текстовое представление (trueилиfalse, или локализованную форму) в вывод. -
b,B,d,o,x,X: Использует целочисленные типы представления со значением static_cast < unsigned char > ( value ) .
Доступные типы представления чисел с плавающей точкой:
-
a: Если указана точность , формирует вывод как при вызове std:: to_chars ( first, last, value, std :: chars_format :: hex , precision ) , где precision — указанная точность; иначе вывод формируется как при вызове std:: to_chars ( first, last, value, std :: chars_format :: hex ) . -
A: аналогичноa, но использует заглавные буквы для цифр выше 9 иPдля обозначения экспоненты. -
e: Формирует вывод как при вызове std:: to_chars ( first, last, value, std :: chars_format :: scientific , precision ) , где precision — указанная точность, или 6, если точность не указана. -
E: аналогичноe, но используетEдля обозначения экспоненты. -
f,F: Формируют вывод как при вызове std:: to_chars ( first, last, value, std :: chars_format :: fixed , precision ) , где precision — указанная точность, или 6, если точность не указана. -
g: Формирует вывод как при вызове std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) , где precision — указанная точность, или 6, если точность не указана. -
G: аналогичноg, но используетEдля обозначения экспоненты. - отсутствует: Если указана точность , формирует вывод как при вызове std:: to_chars ( first, last, value, std :: chars_format :: general , precision ) , где precision — указанная точность; иначе вывод формируется как при вызове std:: to_chars ( first, last, value ) .
Для строчных типов представления бесконечность и NaN форматируются как
inf
и
nan
соответственно.
Для прописных типов представления бесконечность и NaN форматируются как
INF
и
NAN
соответственно.
| std::format спецификатор | std::chars_format | соответствующий std::printf спецификатор |
|---|---|---|
a
,
A
|
std::chars_format::hex |
a
,
A
(но
std::format
не выводит ведущие
0x
или
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
|
| отсутствует | std::chars_format::general если указана точность, иначе кратчайший формат с сохранением точности |
g
если указана точность. Иначе нет соответствующего спецификатора.
|
Доступные типы представления указателей (также используются для std::nullptr_t ):
-
none,
p: Если std::uintptr_t определён, формирует вывод как при вызове std:: to_chars ( first, last, reinterpret_cast < std:: uintptr_t > ( value ) , 16 ) с добавлением префикса0xк выводу; в противном случае вывод определяется реализацией.
|
(начиная с C++26) |
Форматирование экранированных символов и строкСимвол или строка могут быть отформатированы как экранированные , чтобы сделать их более подходящими для отладки или логирования. Экранирование выполняется следующим образом:
Экранированное строковое представление строки конструируется путем экранирования последовательностей кодовых единиц в строке, как описано выше, и заключения результата в двойные кавычки. Экранированное представление символа конструируется путем его экранирования, как описано выше, и заключения результата в одинарные кавычки. Демонстрация в 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: ["ẹ́"] } |
(начиная с C++23) |
Примечания
В большинстве случаев синтаксис похож на старый
%
-форматирование, с добавлением
{}
и с использованием
:
вместо
%
. Например,
"%03.2f"
может быть преобразован в
"{:03.2f}"
.
| Макрос тестирования возможностей | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_lib_format_uchar
|
202311L
|
(C++20)
(DR) |
Форматирование кодовых единиц как беззнаковых целых чисел |
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
| LWG 3721 | C++20 |
ноль не разрешён для поля ширины
в стандартной спецификации формата |
ноль разрешён, если указан
через поле замены |
| P2909R4 | C++20 |
char
или
wchar_t
могут форматироваться как
беззнаковые целые значения вне диапазона |
кодовые единицы преобразуются в соответствующий
беззнаковый тип перед таким форматированием |