C++のformatの使い方について

AI実装検定のご案内

C++のformatとは、文字列の中に数値や文字列などの値を埋め込んだり、表示形式を指定したりするための機能です。

標準ライブラリではstd::formatとして提供されており、C++20から利用できます。

従来のprintfstd::coutでも文字列と値を組み合わせることはできますが、std::formatを使用すると、より簡潔で読みやすいコードを書きやすくなります。

基本的には、フォーマット文字列の中に{}を記述し、その部分へ値を埋め込みます。

#include <format>
#include <iostream>
#include <string>

int main()
{
    std::string name = "Taro";
    int age = 25;

    std::string message =
        std::format("名前は{}、年齢は{}歳です。", name, age);

    std::cout << message << '\n';
}

実行結果は次のようになります。

名前はTaro、年齢は25歳です。

1つ目の{}にはname、2つ目の{}にはageが順番に埋め込まれます。

目次

C++でformatを使うための準備

formatヘッダーをインクルードする

std::formatを利用するには、<format>ヘッダーをインクルードします。

#include <format>

文字列をstd::stringとして保存する場合は、必要に応じて<string>もインクルードします。

#include <format>
#include <string>

画面に出力する場合は、さらに<iostream>を使用します。

#include <format>
#include <iostream>
#include <string>

C++20以降を有効にする

std::formatはC++20から標準ライブラリに追加された機能です。

そのため、コンパイル時にはC++20以降を有効にする必要があります。

GCCであれば、例えば次のように指定します。

g++ -std=c++20 main.cpp

ただし、C++20モードを有効にすれば必ずstd::formatが使えるとは限りません。

std::formatは標準ライブラリの機能であるため、コンパイラだけでなく使用している標準ライブラリの対応状況にも左右されます。

特に古いGCCやlibstdc++では<format>が利用できない場合があります。

std::formatの基本的な使い方

{}に値を埋め込む

std::formatの基本的な書き方は次のとおりです。

std::format("フォーマット文字列", 値1, 値2, ...);

例えば、次のように使用します。

#include <format>
#include <iostream>

int main()
{
    std::cout << std::format("答えは{}です。", 100) << '\n';
}

実行結果は次のようになります。

答えは100です。

{}の部分に、後ろで指定した値が埋め込まれます。

複数の値を埋め込む

{}を複数記述すれば、複数の値を順番に埋め込めます。

std::string result =
    std::format("{} + {} = {}", 10, 20, 30);

結果は次のようになります。

10 + 20 = 30

文字列、整数、浮動小数点数など、さまざまな型の値を組み合わせられるのが特徴です。

formatで文字列を埋め込む方法

std::stringをそのまま指定できる

std::stringはそのまま{}に指定できます。

#include <format>
#include <iostream>
#include <string>

int main()
{
    std::string language = "C++";

    std::cout
        << std::format("使用言語は{}です。", language)
        << '\n';
}

実行結果は次のようになります。

使用言語はC++です。

文字列を何度も+演算子で連結する必要がないため、文章の構造が分かりやすくなります。

formatで整数を表示する方法

整数をそのまま表示する

整数も通常は{}だけで表示できます。

int number = 123;

std::string text = std::format("{}", number);

結果は次のとおりです。

123

さらに、std::formatでは:以降に書式指定を記述することで、数値の表示形式を細かく変更できます。

基本的な形は次のとおりです。

{:書式指定}

整数を2進数・8進数・16進数で表示する方法

2進数で表示する

整数を2進数で表示する場合はbを指定します。

std::cout << std::format("{:b}", 10);

結果は次のとおりです。

1010

8進数で表示する

8進数の場合はoを指定します。

std::cout << std::format("{:o}", 10);

結果は次のようになります。

12

16進数で表示する

16進数を小文字で表示する場合はxを使用します。

std::cout << std::format("{:x}", 255);

結果は次のとおりです。

ff

大文字にする場合はXを使用します。

std::cout << std::format("{:X}", 255);

結果は次のようになります。

FF

0xなどのプレフィックスを付ける

#を指定すると、基数を示すプレフィックスを表示できます。

std::cout << std::format("{:#x}", 255);

結果は次のとおりです。

0xff

2進数でも同様に使用できます。

std::cout << std::format("{:#b}", 10);

結果は次のようになります。

0b1010

formatで数値をゼロ埋めする方法

4桁のゼロ埋めを行う

番号やIDなどを一定の桁数で表示したい場合は、ゼロパディングを利用できます。

例えば、次のコードでは4桁になるように先頭を0で埋めます。

std::cout << std::format("{:04}", 25);

結果は次のとおりです。

0025

0は数値をゼロでパディングする指定で、4は最小表示幅を表します。

8桁にする場合は次のように記述します。

std::cout << std::format("{:08}", 123);

結果は次のとおりです。

00000123

formatで表示幅を指定する方法

左寄せにする

<を指定すると左寄せになります。

std::cout << std::format("|{:<10}|", "C++");

結果は次のようになります。

|C++       |

右寄せにする

>を指定すると右寄せになります。

std::cout << std::format("|{:>10}|", "C++");

結果は次のとおりです。

|       C++|

中央寄せにする

^を指定すると中央寄せになります。

std::cout << std::format("|{:^10}|", "C++");

結果は次のようになります。

|   C++    |

表形式のデータを整えて表示したい場合などに便利です。

空白以外の文字で埋める方法

任意の文字を埋め文字に指定する

幅指定によって発生した余白を、空白以外の文字で埋めることもできます。

例えば、次のように記述します。

std::cout << std::format("{:*^10}", "C++");

結果は次のようになります。

***C++****

*が埋め文字、^が中央揃えを意味します。

左寄せと組み合わせることもできます。

std::cout << std::format("{:-<10}", "C++");

結果は次のとおりです。

C++-------

formatで小数点以下の桁数を指定する方法

固定小数点形式で表示する

浮動小数点数では、小数点以下の桁数を指定できます。

例えば、小数点以下2桁まで表示する場合は次のようにします。

double value = 3.14159265;

std::cout << std::format("{:.2f}", value);

結果は次のとおりです。

3.14

fは固定小数点形式を表し、.2は小数点以下2桁を意味します。

3桁まで表示する場合は次のようにします。

std::cout << std::format("{:.3f}", 3.14159265);

結果は次のとおりです。

3.142

必要に応じて値は丸められます。

formatで指数表記する方法

eを指定して指数表記にする

浮動小数点数を指数表記にする場合はeを指定します。

std::cout << std::format("{:e}", 12345.678);

Eを指定すると、指数部分などを大文字形式で表示できます。

std::cout << std::format("{:E}", 12345.678);

科学技術計算などで大きな数値や小さな数値を扱う場合に便利です。

正の数にもプラス記号を付ける方法

+を指定する

通常、正の数には+記号は付きません。

std::format("{}", 100);

結果は次のとおりです。

100

正の数にも符号を表示したい場合は、+を指定します。

std::format("{:+}", 100);

結果は次のようになります。

+100

負の数の場合は通常どおり-が表示されます。

std::format("{:+}", -100);

結果は次のとおりです。

-100

formatで引数の位置を指定する方法

引数番号を指定する

通常の{}では、引数が左から順番に使用されます。

一方、{0}{1}のように番号を指定すれば、使用する引数の位置を明示できます。

std::format("{0} {1}", "Hello", "World");

結果は次のとおりです。

Hello World

引数番号は0から始まります。

引数の順番を変更する

位置指定を使えば、引数の表示順序を変更できます。

std::format("{1} {0}", "Hello", "World");

結果は次のようになります。

World Hello

同じ引数を複数回使用する

同じ引数を複数箇所で使用することもできます。

std::format("{0} + {0} = {1}", 10, 20);

結果は次のとおりです。

10 + 10 = 20

自動インデックスと手動インデックスは混在できない

{}と{0}を同時に使用しない

std::formatでは、{}による自動インデックスと、{0}などによる手動インデックスを同じフォーマット文字列内で混在させることはできません。

例えば、次のような記述は不正です。

std::format("{} {1}", "A", "B");

自動インデックスを使う場合は、すべて{}に統一します。

std::format("{} {}", "A", "B");

手動インデックスを使う場合は、すべて番号を指定します。

std::format("{0} {1}", "A", "B");

これは単なるコーディング上の推奨ではなく、フォーマット文字列の仕様上の制約です。

波括弧そのものを表示する方法

{{と}}を使用する

std::formatでは{}に特別な意味があるため、波括弧そのものを表示する場合は二重に記述します。

{{ → {
}} → }

例えば、次のようにします。

std::cout << std::format("{{Hello}}");

結果は次のとおりです。

{Hello}

値の前後に波括弧を表示することもできます。

std::cout << std::format("value = {{{}}}", 100);

結果は次のようになります。

value = {100}

std::formatの戻り値

通常はstd::stringが返される

charを使用する通常のstd::formatでは、フォーマット結果がstd::stringとして返されます。

そのため、次のように変数へ保存できます。

std::string text =
    std::format("価格は{}円です。", 1000);

ワイド文字列を使用するオーバーロードではstd::wstringが返されます。

std::wstring text =
    std::format(L"value = {}", 100);

ログメッセージや画面表示用の文字列を作る場合に便利です。

std::format_toの使い方

出力イテレータへ結果を書き込む

std::format_toを使用すると、新しい文字列を返すのではなく、出力イテレータへフォーマット結果を書き込めます。

#include <format>
#include <iterator>
#include <string>

int main()
{
    std::string text;

    std::format_to(
        std::back_inserter(text),
        "{} + {} = {}",
        10,
        20,
        30
    );
}

処理後のtextには次の文字列が格納されます。

10 + 20 = 30

既存の文字列へフォーマット結果を追加したい場合などに便利です。

std::formatted_sizeの使い方

フォーマット後の文字数を調べる

std::formatted_sizeを使用すると、フォーマット結果を実際に文字列として生成せず、必要な文字数を取得できます。

#include <format>
#include <iostream>

int main()
{
    std::size_t size =
        std::formatted_size("Hello {}", "C++");

    std::cout << size << '\n';
}

あらかじめバッファサイズを計算したい場合などに利用できます。

実行時に決まるフォーマット文字列を使う場合

通常のstd::formatではコンパイル時チェックが行われる

通常のstd::formatでは、フォーマット文字列がstd::format_stringとして扱われ、引数型との整合性がコンパイル時に検査されます。

例えば、型に適合しない書式指定を行った場合、コンパイル時に問題を検出できます。

std::format("{:d}", "hello");

この仕組みによって、フォーマット指定と引数型の不一致を早い段階で発見しやすくなっています。

C++20からC++23ではstd::vformatを利用できる

フォーマット文字列がプログラムの実行中に決まる場合、通常のstd::formatstd::stringをそのまま渡すことはできません。

C++20からC++23では、std::vformatを使う方法があります。

#include <format>
#include <string>

std::string fmt = "{}";

std::string result =
    std::vformat(fmt, std::make_format_args(123));

実行時に取得した設定や外部データなどをフォーマット文字列として扱う場合に利用できます。

C++26ではstd::runtime_formatが追加される

C++26では、実行時に決まるフォーマット文字列を扱うためにstd::runtime_formatが追加されています。

そのため、使用しているC++のバージョンによって、実行時フォーマット文字列の扱い方が異なる点に注意が必要です。

formatとprintfの違い

printfは型に対応した書式指定子が必要

printfでは、値の型に応じて書式指定子を変更する必要があります。

例えば、次のように記述します。

printf("name = %s, age = %d\n", name.c_str(), age);

%s%dなどの書式指定子と、実際の引数型を正しく対応させる必要があります。

std::formatは型に応じてフォーマットされる

std::formatでは、多くの場合{}だけで値を扱えます。

std::format("name = {}, age = {}", name, age);

整数、文字列、浮動小数点数などを同じ形式で指定できるため、コードを読みやすくしやすいのが特徴です。

また、通常のstd::formatではフォーマット文字列と引数型の整合性がチェックされるため、printf系関数より型安全なコードを書きやすくなります。

formatとcoutの違い

std::formatは文字列を組み立てる機能

std::formatは、フォーマットされた文字列を生成するための機能です。

std::string text =
    std::format("name = {}, age = {}", name, age);

std::coutは標準出力へ書き込む機能

一方、std::coutは標準出力へデータを書き出すためのストリームです。

std::cout
    << "name = "
    << name
    << ", age = "
    << age
    << '\n';

したがって、std::formatstd::coutは完全に置き換え関係にあるわけではありません。

次のように組み合わせて使うこともできます。

std::cout
    << std::format(
        "name = {}, age = {}\n",
        name,
        age
    );

文章形式の出力では、std::formatを使用したほうが全体の構造を把握しやすい場合があります。

C++のformatでよく使う書式指定一覧

主な書式指定を覚えておく

代表的な書式指定は次のとおりです。

書き方意味表示例
{}通常表示123
{:b}2進数1111011
{:o}8進数173
{:x}16進数・小文字7b
{:X}16進数・大文字7B
{:#x}0x付き16進数0x7b
{:04}4桁ゼロパディング0123
{:<10}左寄せ10文字幅
{:>10}右寄せ10文字幅
{:^10}中央寄せ10文字幅
{:.2f}小数点以下2桁3.14
{:+}正の数にも符号を表示+123
{0}0番目の引数を指定任意
{{{を表示{
}}}を表示}

C++でformatを使うときの注意点

C++17以前では標準のstd::formatは使えない

std::formatはC++20で追加されたため、C++17以前の標準では利用できません。

古い環境では、printfstd::ostringstream、外部ライブラリの{fmt}などを利用する方法があります。

標準ライブラリの対応状況も確認する

std::formatは標準ライブラリの機能です。

そのため、C++20モードを有効にしていても、使用している標準ライブラリが対応していなければ利用できません。

例えば、GCCではlibstdc++側でstd::formatのサポートが追加された時期が比較的新しく、古いGCC環境では<format>が見つからないことがあります。

その場合は、コンパイラと標準ライブラリのバージョンを確認する必要があります。

C++のformatを使えば文字列を読みやすく整形できる

C++のformat、正確にはstd::formatは、C++20から利用できる標準の文字列フォーマット機能です。

基本的には、次のように{}へ値を埋め込みます。

std::format("名前は{}です。", name);

さらに、ゼロパディングもできます。

std::format("{:04}", number);

小数点以下の桁数も指定できます。

std::format("{:.2f}", value);

16進数表示も可能です。

std::format("{:x}", number);

表示幅や配置も指定できます。

std::format("{:>10}", text);

printfと比較すると書式指定と型の不一致を防ぎやすく、std::coutで多数の<<を連結する場合より文章全体を読みやすくできることがあります。

一方で、利用するにはC++20以降と、std::formatに対応した標準ライブラリが必要です。

C++20以降の環境で文字列を組み立てたり、数値を一定の形式で表示したりする場合には、覚えておくと便利な機能です。

以上、C++のformatの使い方についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次