【C++】format() – C++でprintf()風の書式指定を使う
はじめに
C++で値を出力するにはストリームを使いますが、桁数設定や小数点以下の精度表示をするためにわざわざsetw()
やsetprecision()
する必要があるなど、マニピュレータを使用した書式指定が面倒でした。
C言語に慣れているとprintf()
の書式指定方法が便利で、printf()
をC++でも使いたくなるときがあります。Boostライブラリには、似たようなものが用意されていますが、このためだけにBoostをインストールするのも大掛かりです。
しかしながら、ようやくC++20においてprinf()
風の書式指定ができるformat()
が標準仕様に追加されました。このエントリでは、このformat()
についてまとめてみました。
使い方
format()
関数はprintf()
と同じような形で使うことができます。戻り値はstd::string
です。
std::format(書式指定を含む文字列, 値...)
{}
でくくった部分を値で置き換えた文字列を作成します。書式指定は省略可能です。
例
int a = 0; std::string b = "test"; std::string s = std::format("a = {}, b = {}", a, b); // "a = 0, b = test"
{}
の中にprintf()
のような書式指定を書くことができます。詳細な書式は以下になります。([]
は省略可能の意味)
{[ID][:[[埋め文字]桁寄せ][符号][#][0][幅][.精度][L][種別]]}
種類 | 説明 |
---|---|
ID | 引数の番号。何番目の引数で置換するかを表す(0~) |
埋め文字 | 桁数指定したときの余白を埋める文字(省略時は空白) |
桁寄せ | 右寄せ(> )、左寄せ(< )、中央揃え(^ )を表す記号 |
符号 | プラス/マイナスを表示(+ )、負の値でマイナスを表示(- )、正の値で空白を表示(スペース) |
# | 代替表現を使用する(例:16進表示で"0x"を表示する) |
0 | 0で埋める |
幅 | 表示幅 |
精度 | 小数点以下の表示桁数 |
L | ロケールを考慮する |
種別 | 値の表現方法 |
値の表現方法とは、整数を表すd
や浮動小数点数を表すf
、文字列を表すs
などのことです。以下のようなものが指定可能です。
種別 | 意味 |
---|---|
d | 整数 |
b | 2進数表示 |
o | 8進数表示 |
x | 16進数表示(小文字) |
X | 16進数表示(大文字) |
f | 実数(指数表示しない) |
e | 実数(指数表示する) |
g | 実数(必要に応じて指数表示する) |
s | 文字列 |
c | 文字 |
p | ポインタ |
使用例
実際にformat()
を使った例を示します。printf()
による書式指定方法と比較しました。
#include <cstdio>
#include <format>
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 10;
float b = 3.1415926;
unsigned char c = '\x20';
char d[] = "string";
// int型
printf("%d\n", a);
cout << format("{:d}", a) << endl;
// int型、5桁出力、0埋め、+記号表示
printf("%+05d\n", a);
cout << format("{:+05d}", a) << endl;
// float型、10桁出力、小数点以下5桁
printf("%10.5f\n", b);
cout << format("{:10.5f}", b) << endl;
// float型、指数表記
printf("%e\n", b);
cout << format("{:e}", b) << endl;
// unsigned char型、16進表示、2桁
printf("%#02x\n", c);
cout << format("{:#02x}", c) << endl;
// 文字列、10桁出力、右揃え
printf("%10s\n", d);
cout << format("{:10s}", d) << endl;
// 文字列、10桁出力、左揃え
printf("%-10s\n", d);
cout << format("{:<10s}", d) << endl;
// 文字列、10桁出力、中央揃え: printf()ではできない
cout << format("{:^10s}", d) << endl;
// bool型
cout << format("{}", true) << endl;
cout << format("{}", false) << endl;
return 0;
}
出力結果
10
10
+0010
+0010
3.14159
3.14159
3.141593e+00
3.141593e+00
0x20
0x20
string
string
string
string
string
true
false
このように比較すると、%
の代わりに:
で始めることと{}
でくくること以外は、printf()
とほぼ同じ指定で使えることがわかると思います。
まとめ
C++20で導入されたprintf()
風に使える関数format()
についてまとめてみました。%
の代わりに:
で始めることと{}
でくくること以外は、printf()
とほぼ同じ指定で使えます。また、string
を返すのでprintf()
とsprintf()
を使い分けるようなことが不要となります。
C++23以降ではさらに拡張され、vector
やmap
, pair
などにも対応するようです。
(参考)
ディスカッション
コメント一覧
まだ、コメントがありません