名前空間
変種
操作

標準フォーマット仕様 (C++20以降)

From cppreference.com
< cpp‎ | utility‎ | format
 
 
 
 

基本的な型と文字列型の場合、フォーマット仕様は 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進数の表現型が使用されると、代替形式は、符号文字(またはスペース)がある場合はその後に、それ以外の場合は出力値の前に、プレフィックス(0b0、または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から)

利用可能な整数表現型(charwchar_tbool 以外の整数型)は以下の通りです。

  • b: バイナリ形式。std::to_chars(first, last, value, 2) を呼び出したかのように出力を生成します。基数プレフィックスは 0b です。
  • B: b と同じですが、基数プレフィックスは 0B になります。
  • c: 文字 static_cast<CharT>(value) を出力にコピーします。ここで CharT はフォーマット文字列の文字型です。valueCharT の表現可能な値の範囲外の場合、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: 文字を出力にコピーします。
  • bBdoxX: 値を static_cast<unsigned char>(value) または static_cast<std::make_unsigned_t<wchar_t>>(value) として整数表現型を使用します。
  • ?: エスケープされた文字(下記参照)を出力にコピーします。
(C++23から)

bool の利用可能な表現型は以下の通りです。

  • なし、s: テキスト表現(true または false、またはロケール固有の形式)を出力にコピーします。
  • bBdoxX: 値を 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 を使用します。
  • fF: 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はそれぞれ infnan としてフォーマットされます。大文字の表現型の場合、無限大とNaNはそれぞれ INFNAN としてフォーマットされます。

利用可能なポインタ表現型(std::nullptr_t にも使用されます)は以下の通りです。

  • なし、p: std::uintptr_t が定義されている場合、std::to_chars(first, last, reinterpret_cast<std::uintptr_t>(value), 16) を呼び出したかのように出力を生成し、プレフィックス 0x を出力に追加します。それ以外の場合、出力は実装定義です。
  • P: p と同じですが、9を超える桁には大文字を使用し、基数プレフィックスは 0X になります。
(C++26以降)


エスケープされた文字と文字列のフォーマット

文字または文字列は、デバッグやログ記録により適した形式にするためにエスケープされた形式でフォーマットできます。

エスケープは次のように行われます。

  • 文字 C をエンコードする、整形されたコードユニットシーケンスごとに
  • C が以下の表の文字のいずれかである場合、対応するエスケープシーケンスが使用されます。
文字 エスケープシーケンス 注釈
水平タブ(ASCIIエンコーディングでバイト 0x09) \t
ラインフィード - 改行(ASCIIエンコーディングでバイト 0x0a) \n
キャリッジリターン(ASCIIエンコーディングでバイト 0x0d) \r
二重引用符(ASCIIエンコーディングでバイト 0x22) \" 出力が二重引用符で囲まれた文字列の場合にのみ使用されます。
単一引用符(ASCIIエンコーディングでバイト 0x27) \' 出力が単一引用符で囲まれた文字列の場合にのみ使用されます。
バックスラッシュ(ASCIIエンコーディングでバイト 0x5c) \\
  • それ以外の場合、C がスペース文字(ASCIIエンコーディングでバイト 0x20)ではなく、かつ
  • 関連する文字エンコーディングがUnicodeエンコーディングであり、かつ
  • C が、Unicodeプロパティ General_Category の値が Separator (Z) または Other (C) のグループに属するUnicodeスカラー値に対応する場合、または
  • C がエスケープされていない文字に先行されておらず、かつ C がUnicodeプロパティ Grapheme_Extend=Yes を持つUnicodeスカラー値に対応する場合、または
  • 関連する文字エンコーディングがUnicodeエンコーディングではなく、かつ C が実装定義の区切り文字または非表示文字のセットのいずれかである場合
エスケープシーケンスは \u{hex-digit-sequence} となり、ここで hex-digit-sequenceC の、小文字の16進数で表した最短の16進数表現です。
  • それ以外の場合、C はそのままコピーされます。
  • シフトシーケンスであるコードユニットシーケンスは、出力および文字列のそれ以降のデコードに未指定の効果があります。
  • その他のコードユニット(つまり、不正なコードユニットシーケンス内のもの)は、それぞれ \x{hex-digit-sequence} に置き換えられます。ここで hex-digit-sequence は、コードユニットの、小文字の16進数で表した最短の16進数表現です。

文字列のエスケープされた表現は、文字列内のコードユニットシーケンスを上記のようにエスケープし、結果を二重引用符で囲むことで構築されます。

文字のエスケープされた表現は、上記のようにエスケープし、結果を単一引用符で囲むことで構築されます。

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 は、
範囲外の符号なし整数の値として
フォーマットされる可能性があります。
コードユニットは、そのようなフォーマットの前に
対応する符号なし型に変換されます。
English 日本語 中文(简体) 中文(繁體)