このページの内容

書式文字列の構文

このライブラリの書式設定関数、特にfmt::formatとfmt::printは、ここで説明する構文で記述された書式文字列を受け取ります。

書式文字列は、波括弧{と}で囲まれた置換フィールドを埋め込んだ通常のテキストです。置換フィールドの外側にある文字は、そのまま出力にコピーされます。波括弧自体を出力するには二重にします。{{は1つの{を、}}は1つの}を出力します。

置換フィールドは、次の文法で記述されます。

replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
arg_id            ::= integer | identifier
integer           ::= digit+
digit             ::= "0"..."9"
identifier        ::= id_start id_continue*
id_start          ::= "a"..."z" | "A"..."Z" | "_"
id_continue       ::= id_start | digit

arg_idは、どの引数を書式設定するかを選びます。非負整数による位置参照、またはfmt::argで渡した引数の名前に一致する識別子による名前参照を指定できます。arg_idを省略すると、引数は左から右へ順に使われます。この自動インデックス指定は書式文字列全体で統一する必要があります。自動指定と明示的な数値IDを混在させると、コンパイル時エラーになります(実行時にはformat_errorになります)。

:の後に置くformat_specは、値をどのように表示するかを記述します。その文法は型によって異なります。標準の組み込み型で使われる形式は、次の節で説明します。

例:

fmt::format("hello, {}", "world");
// Result: "hello, world"

fmt::format("{1}, {0}!", "world", "hello");
// Result: "hello, world!"

fmt::format("{greeting}, {name}!",
            fmt::arg("greeting", "hi"), fmt::arg("name", "fmt"));
// Result: "hi, fmt!"

format_specの中のwidthやprecision自体を、{}または{arg_id}という入れ子の置換フィールドとして書くこともできます。この場合、実行時に整数引数から値を取得します。入れ子のフィールドに指定できるのはarg_idだけで、その中にさらにformat_specを含めることはできません。

書式指定

次の文法は、整数、浮動小数点数、文字、文字列、真偽値、ポインターという組み込み型と、formatterがfmtのパーサーを再利用するユーザー定義型に共通するformat_specを記述しています。

format_spec ::= [[fill]align][sign]["#"]["0"][width]["." precision]["L"][type]
fill        ::= <a character other than '{' or '}'>
align       ::= "<" | ">" | "^"
sign        ::= "+" | "-" | " "
width       ::= integer | "{" [arg_id] "}"
precision   ::= integer | "{" [arg_id] "}"
type        ::= "a" | "A" | "b" | "B" | "c" | "d" | "e" | "E" | "f" | "F" |
                "g" | "G" | "o" | "p" | "s" | "x" | "X" | "?"

各オプションが意味を持つかどうかは、書式設定する値によって決まります。値の型に適用できないオプションは、可能であればコンパイル時に診断され、それ以外の場合はformat_errorを送出します。

詰め文字と配置

alignは、widthによってフィールドが値の通常の表示より広くなるときに、どこに詰め文字を入れるかを選びます。

オプション 効果
< 左寄せし、右側を埋めます。数値以外の型の既定です。
> 右寄せし、左側を埋めます。数値型の既定です。
^ 中央に配置します。埋める文字数を均等に分けられない場合、余分な1文字は右側に置きます。

fill文字は、{と}以外の単一のUnicodeコードポイントで、書式文字列と同じ方法でエンコードします。既定の空白の代わりに使う詰め文字を指定します。fill文字として認識されるのは、その直後にalign文字がある場合だけです。そうでなければ、別の位置にあるオプションと区別できません。したがって、独自の詰め文字を使うときは配置方法も指定する必要があります。

値の通常の表示がすでにwidth以上の幅を持つ場合、配置指定による見た目の変化はありません。幅に合わせるために値が切り詰められることはありません。

fmt::format("[{:<10}]", "42");   // Result: "[42        ]"
fmt::format("[{:>10}]", "42");   // Result: "[        42]"
fmt::format("[{:^10}]", "42");   // Result: "[    42    ]"
fmt::format("[{:*^10}]", "42");  // Result: "[****42****]"  - '*' as fill

符号

signは、数値の符号をどのように出力するかを制御します。符号付き整数と浮動小数点型だけに適用されます。

オプション 効果
+ 常に符号を出力します(非負の値には+、負の値には-)。
- 負の値にだけ-を出力します。これが既定です。
空白 非負の値には先頭に空白、負の値には-を出力します。符号付き数値を列に揃えるのに便利です。

浮動小数点数の出力では、-0.0の符号が保持されます。

fmt::format("{:+d} {:+d}", 7, -7);  // Result: "+7 -7"
fmt::format("{: d} {: d}", 7, -7);  // Result: " 7 -7"

代替形式(#)

#フラグは代替形式を選びます。正確な意味は表示型によって異なります:

  • 2進、8進、16進で表示する整数には、適切な基数接頭辞(0b/0B、0、0x/0X)を前に付けます。接頭辞の大文字・小文字は型指定子に従います。xには0x、Xには0Xという対応です。
  • 浮動小数点数では、本来なら小数部の数字が出力されない場合にも小数点を表示させ、g/Gの表示型が仮数部の末尾のゼロを取り除くことを防ぎます。

数値以外の型では、#フラグは使えません。

ゼロ埋め(0)

widthの直前に0を置くと、数値型に対して符号を考慮したゼロ埋めが有効になります。ゼロは、符号(または基数接頭辞がある場合はその接頭辞)と最上位桁の間に挿入されます。そのため、符号や0x接頭辞は空白で数字から離されず、数字に隣接したままになります。たとえば、120に{:+08d}を適用すると、+0000120になります。

ゼロ埋めの性質:

  • 数値型だけに適用されます。
  • infやnanには影響しません。
  • 明示的なalignも指定されている場合は無視されます。

幅

widthは、フィールドが占める文字数の最小値を表す非負の10進整数です。書式設定した値がwidthより短ければ、alignとfillに従って埋めます。長ければ、値全体を出力します。widthが原因で値が切り詰められることはありません。

実行時にwidthを指定するには、次の引数を使う{}、または位置や名前で整数引数を参照する{arg_id}をフィールドに記述します。

文字列の書式設定では、Unicodeを考慮した推定で「幅」を表示列数として測ります。東アジアの幅広文字・全角文字と一般的な絵文字の範囲は2列、それ以外は1列と数えます。これにより、ラテン文字とCJK文字を組み合わせた等幅表示でも、固定のwidth値が見た目に一貫した幅になります。

fmt::format("[{:6}]", 42);
// Result: "[    42]"  - right-aligned by default
fmt::format("[{:6}]", "hi");
// Result: "[hi    ]"  - left-aligned by default
fmt::format("[{:{}}]", 42, 6);
// Result: "[    42]"  - width from an argument

精度

precisionは、.の後に置く非負の10進整数で、その意味は書式設定する値によって異なります。widthと同じく、入れ子の置換フィールドで指定して実行時に評価することもできます。

型 .precisionの意味
e, E, f, F 小数点以下に出力する桁数。
g, G 有効数字の総数。
a, A 16進の仮数部で、小数点以下の桁数。省略すると、値を正確に往復変換できるだけの桁数を出力します。
文字列(s、?、または既定) 値からコピーするコードポイント数の上限。

整数、文字、真偽値、ポインター型ではprecisionを指定できません。precisionでC文字列から取り出す文字数を制限する場合でも、その文字列はヌル終端されている必要があります。

fmt::format("{:.2f}", 3.14159);        // Result: "3.14"
fmt::format("{:.3g}", 3.14159);        // Result: "3.14"
fmt::format("{:.4}", "hello, world");  // Result: "hell"
fmt::format("{:.{}f}", 3.14159, 4);
// Result: "3.1416"  - precision from an argument

ロケール(L)

Lフラグは、数値型に対してロケールに応じた書式設定を選びます。フォーマッターは書式設定関数に渡されたC++ロケールを調べ、渡されていなければグローバルロケールを使います。そのロケールの桁区切り文字と、浮動小数点数では小数点を挿入します。このフラグは数値以外の型には影響しません。

auto loc = std::locale("en_US.UTF-8");
fmt::format(loc, "{:L}", 1234567890);     // Result: "1,234,567,890"
fmt::format(loc, "{:.2Lf}", 1234567.89);  // Result: "1,234,567.89"

表示型

値の表現はtypeで選びます。以下では、適用される値の種類ごとに指定子をまとめています。

整数、真偽値、文字:

型 効果
b 2進数。#フラグで0b接頭辞を付けます。
B 2進数。#フラグで0B接頭辞を付けます。
c 整数を、そのコードポイントの文字として表示します。boolには使えません。
d 10進数。整数型の既定です。
o 8進数。
x 16進数で、数字に小文字を使います。#フラグで0x接頭辞を付けます。
X 16進数で、数字に大文字を使います。#フラグで0X接頭辞を付けます。
指定なし 整数にはd、文字にはc、boolにはテキスト表現(true/false)を使う場合と同じです。
fmt::format("{:d} {:#x} {:#o} {:#b}", 42, 42, 42, 42);
// Result: "42 0x2a 052 0b101010"

fmt::format("{:#06x}", 0xfe);  // # adds the prefix, 06 zero-pads to width 6
// Result: "0x00fe"

浮動小数点数:

型 効果
a 16進の仮数部を使う形式(例:1.8p+1)。数字には小文字を使い、2進指数には小文字のpを使います。#フラグで0x接頭辞を付けます。
A aと同じですが、全体に大文字を使います。
e 10進指数に小文字のeを使う科学表記。
E 大文字のEを使う科学表記。
f 固定小数点表記。
F fと同じですが、nanはNAN、infはINFと表示します。
g 一般形式。指数が−4未満、または精度以上になる場合は科学表記、それ以外は固定小数点表記を使います。#を指定しない限り、小数部の末尾のゼロは取り除かれます。精度0は1として扱います。
G gと同じですが、指数にはE、INF/NANには大文字を使います。
指定なし 往復変換可能な最短表現。書式設定した値を同じ浮動小数点型として読み戻すと、入力がビット単位で再現されます。

文字列と文字:

型 効果
s 通常の文字列出力。文字列型とboolの既定で、boolはtrueまたはfalseとして表示されます。
c 文字出力。文字型の既定です。boolには使えません。
? デバッグ出力。値を、文字なら単一引用符、文字列なら二重引用符で囲みます。表示不能な文字、非ASCII文字、特殊文字は、\n、\t、\"、\u{...}などのC形式のエスケープシーケンスでエスケープします。
指定なし 文字列とboolにはs、文字にはcを使う場合と同じです。
fmt::format("{}",   "tab\there");  // Result contains a literal tab character.
fmt::format("{:?}", "tab\there");  // Result: "\"tab\\there\""

ポインター:

型 効果
p 0x接頭辞を付けた16進アドレス。ポインター型の既定です。
指定なし pを使う場合と同じです。

C文字列(char*またはconst char*)では、文字列の表示型とpの両方を使えます。そのため、同じ値をテキストとしてもアドレスとしても書式設定できます。

chronoの書式指定

chronoの期間型・時点型とstd::tmの書式指定は、次の構文を使います:

chrono_format_spec ::= [[fill]align][width]["." precision][chrono_specs]
chrono_specs       ::= conversion_spec |
                       chrono_specs (conversion_spec | literal_char)
conversion_spec    ::= "%" [padding_modifier] [locale_modifier] chrono_type
literal_char       ::= <a character other than '{', '}' or '%'>
padding_modifier   ::= "-" | "_"  | "0"
locale_modifier    ::= "E" | "O"
chrono_type        ::= "a" | "A" | "b" | "B" | "c" | "C" | "d" | "D" | "e" |
                       "F" | "g" | "G" | "h" | "H" | "I" | "j" | "m" | "M" |
                       "n" | "p" | "q" | "Q" | "r" | "R" | "S" | "t" | "T" |
                       "u" | "U" | "V" | "w" | "W" | "x" | "X" | "y" | "Y" |
                       "z" | "Z" | "%"

リテラル文字は、そのまま出力にコピーされます。精度を指定できるのは、表現型が浮動小数点型であるstd::chrono::durationだけです。

利用できる表示型(chrono_type)は次のとおりです:

型 意味
'a' 曜日の短縮名(例:"Sat")。値に有効な曜日が含まれていない場合、format_error型の例外を送出します。
'A' 曜日の完全な名前(例:"Saturday")。値に有効な曜日が含まれていない場合、format_error型の例外を送出します。
'b' 月の短縮名(例:"Nov")。値に有効な月が含まれていない場合、format_error型の例外を送出します。
'B' 月の完全な名前(例:"November")。値に有効な月が含まれていない場合、format_error型の例外を送出します。
'c' 日付と時刻の表現(例:"Sat Nov 12 22:04:00 1955")。修飾したコマンド%Ecは、ロケールの代替の日付・時刻表現を出力します。
'C' 年を100で割り、切り下げた値(例:"19")。結果が10進1桁の場合、先頭に0を付けます。修飾したコマンド%ECは、ロケールの世紀の代替表現を出力します。
'd' 月内の日を10進数で表します。結果が10進1桁の場合、先頭に0を付けます。修飾したコマンド%Odは、ロケールの代替表現を出力します。
'D' %m/%d/%yと同じです(例:"11/12/55")。
'e' 月内の日を10進数で表します。結果が10進1桁の場合、先頭に空白を付けます。修飾したコマンド%Oeは、ロケールの代替表現を出力します。
'F' %Y-%m-%dと同じです(例:"1955-11-12")。
'g' ISO週基準の年の下2桁を10進数で表します。結果が1桁の場合、先頭に0を付けます。
'G' ISO週基準の年を10進数で表します。結果が4桁未満の場合、左側を0で埋めて4桁にします。
'h' %bと同じです(例:"Nov")。
'H' 時を24時間制の10進数で表します。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%OHは、ロケールの代替表現を出力します。
'I' 時を12時間制の10進数で表します。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%OIは、ロケールの代替表現を出力します。
'j' 書式設定する型がdurationの特殊化の場合、日数を桁埋めなしの10進数で表します。それ以外の場合は、年内の日を10進数で表し、1月1日を001とします。この場合、結果が3桁未満なら、左側を0で埋めて3桁にします。
'm' 月を10進数で表します。1月は01です。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%Omは、ロケールの代替表現を出力します。
'M' 分を10進数で表します。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%OMは、ロケールの代替表現を出力します。
'n' 改行文字。
'p' 12時間制で使うAM/PMの表記。
'q' 期間の単位を表す接尾辞。
'Q' 期間の数値(.count()で取得した値と同様)。
'r' 12時間制の時刻(例:"10:04:00 PM")。
'R' %H:%Mと同じです(例:"22:04")。
'S' 秒を10進数で表します。秒数が10未満の場合、先頭に0を付けます。入力の精度を秒で正確に表せない場合は、入力の精度に合わせた精度の固定形式の10進浮動小数点数で表示します。ただし、小数点以下18桁以内で10進浮動小数点秒に変換できない場合は、マイクロ秒の精度を使います。修飾したコマンド%OSは、ロケールの代替表現を出力します。
't' 水平タブ文字。
'T' %H:%M:%Sと同じです。
'u' ISOの曜日を10進数(1〜7)で表し、月曜日を1とします。修飾したコマンド%Ouは、ロケールの代替表現を出力します。
'U' 年内の週番号を10進数で表します。その年の最初の日曜日が第01週の初日です。同じ年のそれより前の日は第00週に入ります。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%OUは、ロケールの代替表現を出力します。
'V' ISO週基準の週番号を10進数で表します。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%OVは、ロケールの代替表現を出力します。
'w' 曜日を10進数(0〜6)で表し、日曜日を0とします。修飾したコマンド%Owは、ロケールの代替表現を出力します。
'W' 年内の週番号を10進数で表します。その年の最初の月曜日が第01週の初日です。同じ年のそれより前の日は第00週に入ります。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%OWは、ロケールの代替表現を出力します。
'x' 日付の表現(例:"11/12/55")。修飾したコマンド%Exは、ロケールの代替の日付表現を出力します。
'X' 時刻の表現(例:"10:04:00")。修飾したコマンド%EXは、ロケールの代替の時刻表現を出力します。
'y' 年の下2桁を10進数で表します。結果が1桁の場合、先頭に0を付けます。修飾したコマンド%Oyは、ロケールの代替表現を出力します。修飾したコマンド%Eyは、%ECからの差のロケールによる代替表現を出力します(年だけ)。
'Y' 年を10進数で表します。結果が4桁未満の場合、左側を0で埋めて4桁にします。修飾したコマンド%EYは、ロケールの完全な年の代替表現を出力します。
'z' UTCからのオフセットをISO 8601:2004形式で表します。たとえば、-0430はUTCより4時間30分遅れていることを示します。オフセットがゼロの場合は+0000を使います。修飾したコマンド%Ezと%Ozは、時と分の間に:を挿入します(-04:30)。オフセット情報が利用できない場合は、format_error型の例外を送出します。
'Z' タイムゾーンの略称。タイムゾーンの略称が利用できない場合は、format_error型の例外を送出します。
'%' %文字。

日付の要素を持つ指定子、たとえば月内の日を表す'd'は、std::tmと時点に対してだけ有効で、期間には使えません。

利用できる桁埋め修飾子(padding_modifier)は次のとおりです:

型 意味
'_' 数値の結果を空白で埋めます。
'-' 数値の結果の文字列を埋めません。
'0' 数値の結果の文字列をゼロで埋めます。

これらの修飾子を使える表示型は、'H'、'I'、'M'、'S'、'U'、'V'、'W'、'Y'、'd'、'j'、'm'だけです。

例:

#include <fmt/chrono.h>

auto t = std::tm();
t.tm_year = 2010 - 1900;
t.tm_mon = 7;
t.tm_mday = 4;
t.tm_hour = 12;
t.tm_min = 15;
t.tm_sec = 58;
fmt::print("{:%Y-%m-%d %H:%M:%S}", t);
// Prints: 2010-08-04 12:15:58

範囲の書式指定

範囲型の書式指定は、次の構文を使います:

range_format_spec ::= ["n"][range_type][":" range_underlying_spec]

'n'オプションは、範囲の前後の括弧を付けずに書式設定します。

range_typeで利用できる表示型は次のとおりです:

型 意味
指定なし 既定の書式。
's' 文字列形式。範囲を文字列として書式設定します。
'?⁠s' デバッグ形式。範囲をエスケープした文字列として書式設定します。

range_typeが's'または'?s'の場合、範囲の要素型は文字型でなければなりません。'n'オプションとrange_underlying_specは、's'および'?s'と併用できません。

range_underlying_specは、範囲の要素型のフォーマッターに基づいて解析されます。

既定では、文字や文字列の範囲はエスケープされ、引用符で囲んで出力されます。ただし、range_underlying_specを指定した場合は、空であっても、その指定に従って文字や文字列が出力されます。

例:

fmt::print("{}", std::vector{10, 20, 30});
// Output: [10, 20, 30]
fmt::print("{::#x}", std::vector{10, 20, 30});
// Output: [0xa, 0x14, 0x1e]
fmt::print("{}", std::vector{'h', 'e', 'l', 'l', 'o'});
// Output: ['h', 'e', 'l', 'l', 'o']
fmt::print("{:n}", std::vector{'h', 'e', 'l', 'l', 'o'});
// Output: 'h', 'e', 'l', 'l', 'o'
fmt::print("{:s}", std::vector{'h', 'e', 'l', 'l', 'o'});
// Output: "hello"
fmt::print("{:?s}", std::vector{'h', 'e', 'l', 'l', 'o', '\n'});
// Output: "hello\n"
fmt::print("{::}", std::vector{'h', 'e', 'l', 'l', 'o'});
// Output: [h, e, l, l, o]
fmt::print("{::d}", std::vector{'h', 'e', 'l', 'l', 'o'});
// Output: [104, 101, 108, 108, 111]
fmt::print("{:n:f}", std::array{std::numbers::pi, std::numbers::e});
// Output: 3.141593, 2.718282

組み合わせた例

次の例は、ここまでに説明した入れ子の置換フィールド、詰め文字、中央配置を組み合わせ、メッセージの周囲に固定幅の枠を描きます:

fmt::print(
    "┌{0:─^{2}}┐\n"
    "│{1: ^{2}}│\n"
    "└{0:─^{2}}┘\n", "", "Hello, world!", 20);

出力:

┌────────────────────┐
│   Hello, world!    │
└────────────────────┘