標準フォーマット仕様 (C++20以降)
基本的な型と文字列型の場合、フォーマット仕様は Pythonのフォーマット仕様に基づいています。
フォーマット仕様の構文は次のとおりです。
fill-and-align (オプション) sign (オプション) #(オプション) 0(オプション) width (オプション) precision (オプション) L(オプション) type (オプション) |
|||||||||
sign、#、0 オプションは、整数または浮動小数点数の表現型が使用されている場合にのみ有効です。
目次 |
[編集] 埋めと配置
fill-and-align は、オプションの埋め文字({または}以外の任意の文字)と、それに続く配置オプション <、>、^のいずれかです。
埋め文字が指定されない場合、デフォルトはスペース文字になります。Unicodeエンコーディングのフォーマット仕様では、埋め文字は単一のUnicodeスカラー値に対応している必要があります。
配置オプションの意味は以下の通りです。
-
<: フォーマットされた引数を、利用可能なスペースの先頭に配置します。フォーマットされた引数の後に 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 オプションは以下のいずれかになります。
-
+: 正数と負数の両方に符号を使用することを示します。+符号は、正数の出力値の前に挿入されます。 -
-: 負数にのみ符号を使用することを示します(これがデフォルトの動作です)。 - space: 正数には先頭のスペースを、負数にはマイナス符号を使用することを示します。
負のゼロは負数として扱われます。
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"); }
# オプションは、変換に代替形式を使用させます。
- 整数型の場合、バイナリ、オクタル、または16進数の表現型が使用されると、代替形式は、符号文字(またはスペース)がある場合はその後に、それ以外の場合は出力値の前に、プレフィックス(
0b、0、または0x)を出力値に挿入します。 - 浮動小数点数型の場合、代替形式は、有限値の変換結果が、たとえ後に桁がなくても、常に小数点文字を含むようにします。通常、これらの変換の結果に小数点文字が現れるのは、後に桁がある場合のみです。さらに、
gおよびG変換では、結果から末尾のゼロは削除されません。
0 オプションは、フィールド幅に合わせて、フィールドを先頭のゼロで埋めます(符号または基数の表示の後)。ただし、無限大またはNaNに適用される場合を除きます。0 文字と配置オプションの両方が指定されている場合、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 is ignored because of '<' }
[編集] 幅と精度
width は、正の10進数またはネストされた置換フィールド({}または{n})のいずれかです。指定されている場合、最小フィールド幅を指定します。
precision は、ピリオド(.)の後に、非負の10進数またはネストされた置換フィールドが続きます。このフィールドは、精度または最大フィールドサイズを示します。浮動小数点数型と文字列型でのみ使用できます。
- 浮動小数点数型の場合、このフィールドはフォーマット精度を指定します。
- 文字列型の場合、出力にコピーされる文字列のプレフィックスの推定幅(下記参照)の上限を提供します。Unicodeエンコーディングの文字列の場合、出力にコピーされるテキストは、推定幅が精度を超えない最初の完全な拡張グラフェムクラスターの最も長いプレフィックスです。
width または precision にネストされた置換フィールドが使用され、対応する引数が整数型(C++23まで)標準符号付きまたは符号なし整数型(C++23以降)ではない場合、または負の値である場合、std::format_error 型の例外がスローされます。
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
文字列の幅は、ターミナルで表示するのに適切な列位置の推定数として定義されます。
幅の計算目的で、文字列は実装定義のエンコーディングであると仮定されます。幅の計算方法は未指定ですが、Unicodeエンコーディングの文字列の場合、実装は文字列の幅を、その拡張グラフェムクラスターの最初のコードポイントの推定幅の合計として推定する必要があります。推定幅は、次のコードポイントで2であり、それ以外の場合は1です。
- Unicodeプロパティ
East_Asian_Widthの値が Fullwidth (F) または Wide (W) である任意のコードポイント - U+4DC0 - U+4DFF (易経六十四卦記号)
- 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}", "🐱🐱🐱") == "🐱🐱."); }
[編集] L (ロケール固有のフォーマット)
L オプションは、ロケール固有の形式を使用させます。このオプションは算術型でのみ有効です。
- 整数型の場合、ロケール固有の形式は、コンテキストのロケールに従って適切な桁区切り文字を挿入します。
- 浮動小数点数型の場合、ロケール固有の形式は、コンテキストのロケールに従って適切な桁区切り文字と小数点文字を挿入します。
boolのテキスト表現の場合、ロケール固有の形式は、std::numpunct::truename または std::numpunct::falsename で取得されたものと同様の適切な文字列を使用します。
[編集] 型
type オプションは、データの表示方法を決定します。
利用可能な文字列表現型は以下の通りです。
- なし、
s: 文字列を出力にコピーします。
|
(C++23から) |
利用可能な整数表現型(char、wchar_t、bool 以外の整数型)は以下の通りです。
-
b: バイナリ形式。std::to_chars(first, last, value, 2)を呼び出したかのように出力を生成します。基数プレフィックスは0bです。 -
B:bと同じですが、基数プレフィックスは0Bになります。 -
c: 文字 static_cast<CharT>(value) を出力にコピーします。ここでCharTはフォーマット文字列の文字型です。valueがCharTの表現可能な値の範囲外の場合、std::format_error 例外がスローされます。 -
d: 10進数形式。std::to_chars(first, last, value)を呼び出したかのように出力を生成します。 -
o: 8進数形式。std::to_chars(first, last, value, 8)を呼び出したかのように出力を生成します。基数プレフィックスは、対応する引数値がゼロでない場合は0、それ以外の場合は空になります。 -
x: 16進数形式。std::to_chars(first, last, value, 16)を呼び出したかのように出力を生成します。基数プレフィックスは0xです。 -
X:xと同じですが、9を超える桁には大文字を使用し、基数プレフィックスは0Xになります。 - なし:
dと同じです。
char および wchar_t の利用可能な表現型は以下の通りです。
- なし、
c: 文字を出力にコピーします。 -
b、B、d、o、x、X: 値を static_cast<unsigned char>(value) または static_cast<std::make_unsigned_t<wchar_t>>(value) として整数表現型を使用します。
|
(C++23から) |
bool の利用可能な表現型は以下の通りです。
- なし、
s: テキスト表現(trueまたはfalse、またはロケール固有の形式)を出力にコピーします。 -
b、B、d、o、x、X: 値を static_cast<unsigned char>(value) として整数表現型を使用します。
利用可能な浮動小数点数表現型は以下の通りです。
-
a: precision が指定されている場合、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を使用します。 - なし: precision が指定されている場合、
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::nullptr_t にも使用されます)は以下の通りです。
- なし、
p:std::uintptr_tが定義されている場合、std::to_chars(first, last, reinterpret_cast<std::uintptr_t>(value), 16)を呼び出したかのように出力を生成し、プレフィックス0xを出力に追加します。それ以外の場合、出力は実装定義です。
|
(C++26以降) |
エスケープされた文字と文字列のフォーマット文字または文字列は、デバッグやログ記録により適した形式にするためにエスケープされた形式でフォーマットできます。 エスケープは次のように行われます。
文字列のエスケープされた表現は、文字列内のコードユニットシーケンスを上記のようにエスケープし、結果を二重引用符で囲むことで構築されます。 文字のエスケープされた表現は、上記のようにエスケープし、結果を単一引用符で囲むことで構築されます。 このコードを実行 #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 は、 範囲外の符号なし整数の値として |
フォーマットされる可能性があります。 コードユニットは、そのようなフォーマットの前に |