【Qt入門】QTextStream::numberFlags()を使った数値出力のカスタマイズ方法

2025-05-27

QTextStream::numberFlags() は、Qt プログラミングにおける QTextStream クラスのメンバ関数で、数値の出力形式を制御するためのフラグ群を取得します。

QTextStream は、テキストの読み書きを便利に行うためのクラスで、ファイル、バイト配列、QString など、様々なI/Oデバイスを扱えます。数値を出力する際に、例えば16進数で表示するか、常に符号を表示するか、小数点以下の桁数を強制するか、といった細かな設定をしたい場合に numberFlags() で現在の設定を取得し、setNumberFlags() で変更します。

numberFlags() が返す QTextStream::NumberFlags とその内訳

QTextStream::NumberFlags は、QTextStream::NumberFlag 列挙型の値の組み合わせ(ビットフラグ)です。主な NumberFlag の種類とその意味は以下の通りです。

  • QTextStream::UppercaseDigits:

    • 10より大きい数字(A, B, C...)を表現する際に、大文字を使用します。主に16進数で影響します。
    • 例: 0xABCDEF (16進数)
  • QTextStream::UppercaseBase:

    • 基数を示すプレフィックス("0x", "0b" など)を大文字で表示します。
    • ShowBase と組み合わせて使用します。
    • 例: 0XABC (16進数)
  • QTextStream::ForceSign:

    • 正の数に対しても常に符号(+)を表示します。
    • 例: -5-55+5
  • QTextStream::ForcePoint:

    • 浮動小数点数を表示する際に、小数点以下の桁がなくても常に小数点を表示します。
    • 例: 123. ではなく 123.0 (このフラグが設定されている場合)
  • QTextStream::ShowBase:

    • 基数(10進数、16進数など)を示すプレフィックス(例: 16進数の "0x"、8進数の "0"、2進数の "0b")を表示します。
    • 例: 0xABC (16進数), 0123 (8進数), 0b1011 (2進数)
#include <QTextStream>
#include <QString>
#include <QDebug> // デバッグ出力用

int main() {
    QString output;
    QTextStream stream(&output);

    // デフォルトのフラグを表示(通常は空のQFlags)
    qDebug() << "デフォルトのフラグ:" << stream.numberFlags();

    // 16進数で基数を表示し、大文字を使用する設定
    stream.setNumberFlags(QTextStream::ShowBase | QTextStream::UppercaseBase | QTextStream::UppercaseDigits);
    stream << "Hex: " << 255 << Qt::endl; // 0xFF と出力されます

    // 正の数に符号を強制表示する設定
    stream.setNumberFlags(stream.numberFlags() | QTextStream::ForceSign); // 既存のフラグにForceSignを追加
    stream << "Signed: " << 100 << " " << -50 << Qt::endl; // +100 -50 と出力されます

    // 小数点を強制表示する設定
    stream.setNumberFlags(stream.numberFlags() | QTextStream::ForcePoint);
    stream << "Float: " << 123.0 << Qt::endl; // 123.0 と出力されます

    qDebug() << "設定後の出力:\n" << output;

    return 0;
}


QTextStream::numberFlags() は数値の出力フォーマットを制御するための便利な機能ですが、使い方を誤ると意図しない結果になることがあります。以下に、よくあるエラーとそのトラブルシューティングを挙げます。

フラグの設定が期待通りに反映されない

問題
setNumberFlags() でフラグを設定したはずなのに、数値の出力フォーマットが変わらない。

原因とトラブルシューティング

  • QTextStream マニピュレータとの混同
    QTextStream には、showbaseforcesignhexdec といったマニピュレータも用意されています。これらは内部的に setNumberFlags()setIntegerBase() を呼び出しますが、マニピュレータと setNumberFlags() を併用すると、意図しない挙動になる可能性があります。一貫した方法でフォーマットを設定することをお勧めします。

    // BAD: マニピュレータとsetNumberFlags()を混在させると、どちらが優先されるか分かりにくい
    stream << Qt::hex << 255;
    stream.setNumberFlags(QTextStream::ForceSign);
    
  • 既存のフラグをクリアし忘れている
    特定のフラグを無効にしたい場合は、現在のフラグからビット AND (&) 演算とビット否定 (~) 演算を組み合わせてクリアする必要があります。

    // ShowBase フラグを無効にする
    stream.setNumberFlags(stream.numberFlags() & ~QTextStream::ShowBase);
    
  • 既存のフラグを上書きしている
    setNumberFlags() は、引数で渡されたフラグで既存のすべてのフラグを上書きします。特定のフラグを追加したい場合は、現在のフラグを取得してビット OR (|) 演算で結合する必要があります。

    // BAD: ForceSign だけを有効にして、ShowBaseは無効になる
    stream.setNumberFlags(QTextStream::ForceSign);
    
    // GOOD: 既存のフラグにForceSignを追加
    stream.setNumberFlags(stream.numberFlags() | QTextStream::ForceSign);
    
  • setNumberFlags() の呼び出し忘れ、または間違ったタイミングでの呼び出し
    setNumberFlags() は、その呼び出し以降の出力に影響します。数値を出力する前に正しく設定されているか確認してください。複数の数値を出力する間にフラグを変更したい場合は、その都度 setNumberFlags() を呼び出す必要があります。

    QTextStream stream(&output);
    stream << 123; // デフォルトのフォーマット
    
    stream.setNumberFlags(QTextStream::ShowBase | QTextStream::Hex); // ここで設定
    stream << 255; // 0xff と出力される
    
    stream.setNumberFlags(QTextStream::ForceSign); // 別途設定
    stream << 100; // +100 と出力される
    

浮動小数点数の出力が期待通りにならない

問題
ForcePoint フラグを設定しても、浮動小数点数の小数点以下の挙動が期待通りにならない。

原因とトラブルシューティング

  • setRealNumberPrecision() や setRealNumberNotation() との兼ね合い
    QTextStream::ForcePoint は、小数点以下の桁数がなくても小数点を表示するフラグですが、浮動小数点数の全体の表示形式(固定小数点表記、指数表記など)や精度は setRealNumberPrecision()setRealNumberNotation() で制御されます。これらの設定が ForcePoint の挙動に影響を与えることがあります。

    例えば、setRealNumberPrecision(0) を設定すると、小数点以下が表示されなくなるため、ForcePoint の効果も薄れてしまいます。

    stream.setNumberFlags(QTextStream::ForcePoint);
    stream.setRealNumberPrecision(2); // 小数点以下2桁を表示
    stream << 123.0; // 123.00 と出力される(ForcePointの効果で小数点が表示される)
    
    stream.setRealNumberPrecision(0); // 小数点以下を表示しない
    stream << 123.0; // 123 と出力される(ForcePointの効果が打ち消される)
    

16進数や2進数で数字が小文字になる、またはプレフィックスが表示されない

問題
ShowBaseUppercaseDigits を設定したのに、16進数の 'a'〜'f' が小文字になったり、"0x" などのプレフィックスが表示されない。

原因とトラブルシューティング

  • setIntegerBase() の設定
    QTextStream はデフォルトで基数を自動検出しますが、setIntegerBase() を使用して明示的に基数を設定できます。16進数として出力したい場合は、stream << Qt::hex マニピュレータを使用するか、setIntegerBase(16) を呼び出す必要があります。

    stream.setNumberFlags(QTextStream::ShowBase | QTextStream::UppercaseDigits);
    // デフォルトは10進数なので、この設定だけでは16進数にはならない
    stream << 255; // 255 と出力される
    
    // 16進数として出力するには、Qt::hex マニピュレータを使うか、setIntegerBase() を呼び出す
    stream << Qt::hex << 255; // 0xFF と出力される
    
  • ShowBase フラグの設定漏れ
    UppercaseBaseUppercaseDigits は、ShowBase と組み合わせて初めて意味をなします。基数を示すプレフィックス("0x" など)を表示しない限り、大文字/小文字の区別は関係ありません。

    // BAD: UppercaseDigitsだけでは、0xFF のように大文字にならない
    stream.setNumberFlags(QTextStream::UppercaseDigits);
    stream << Qt::hex << 255; // ff と出力される
    
    // GOOD: ShowBase と UppercaseDigits を組み合わせる
    stream.setNumberFlags(QTextStream::ShowBase | QTextStream::UppercaseDigits);
    stream << Qt::hex << 255; // 0xFF と出力される
    

QTextStream の状態がリセットされる場合がある

問題
一度設定した numberFlags が、予期せずデフォルトに戻ってしまったり、他の設定に上書きされたりする。

原因とトラブルシューティング

  • reset() の呼び出し
    QTextStream::reset() メソッドは、ストリームの書式設定(フィールド幅、パディング文字、数値フラグ、実数表記など)をデフォルト値にリセットします。デバッグ目的などで reset() を呼び出している場合、設定が失われる可能性があります。

  • 新しい QTextStream オブジェクトの作成
    QTextStream オブジェクトを新しく作成すると、そのオブジェクトはデフォルトの状態(フラグもデフォルト)で初期化されます。前の QTextStream オブジェクトの設定は引き継がれません。 同じストリームに対して一貫した設定を維持したい場合は、同じ QTextStream インスタンスを使い続けるか、必要に応じて毎回設定を再適用する必要があります。

全体的なトラブルシューティングのヒント

  • Qt ドキュメントを参照する
    QTextStream の詳細な動作や、各フラグの意味、他のフォーマット設定との兼ね合いについては、Qt の公式ドキュメントが最も正確な情報源です。
  • シンプルなコードでテストする
    複雑な処理の中で問題が発生している場合、QTextStream の設定と出力に関する部分だけを切り出して、最小限のコードで動作を確認すると原因を特定しやすくなります。
  • 現在のフラグを確認する
    stream.numberFlags() の戻り値を qDebug() などで出力し、設定が正しく反映されているかを確認します。


QTextStream::numberFlags() 関連プログラミング例

QTextStream::numberFlags() は、数値の出力フォーマットを制御するための非常に便利な機能です。ここでは、さまざまなフラグの組み合わせと、それらが数値出力にどのように影響するかを示す具体的なコード例を挙げます。

準備

これらの例を実行するには、Qtプロジェクトを作成し、.pro ファイルに QT += core を追加するか、CMakeを使用している場合は find_package(Qt6 COMPONENTS Core) を追加して Qt::Core をリンクするように設定してください。

// main.cpp
#include <QCoreApplication> // コンソールアプリケーションの場合
#include <QTextStream>
#include <QString>
#include <QDebug> // デバッグ出力用

// ヘルパー関数: フラグ設定と出力を簡素化
void printNumberWithFlags(QTextStream& stream, int number, const QString& description) {
    stream << description << ": " << number << Qt::endl;
}

void printDoubleWithFlags(QTextStream& stream, double number, const QString& description) {
    stream << description << ": " << number << Qt::endl;
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv); // コンソールアプリケーションの基本的な初期化

    QString outputString;
    QTextStream stream(&outputString, QIODevice::WriteOnly); // QStringへの書き込みストリーム

    qDebug() << "--- QTextStream::numberFlags() の例 ---";

    // ----------------------------------------------------
    // 1. デフォルトの動作
    // ----------------------------------------------------
    qDebug() << "\n--- 1. デフォルトの動作 ---";
    // デフォルトでは、ほとんどのフラグは設定されていません。
    // 整数は10進数、符号は負の数のみ、浮動小数点数は必要に応じて小数点が表示されます。
    stream.setNumberFlags(QTextStream::NumberFlags()); // 明示的にデフォルトにリセット
    stream << "Default Int: " << 123 << Qt::endl;
    stream << "Default Negative Int: " << -45 << Qt::endl;
    stream << "Default Double (no frac): " << 789.0 << Qt::endl;
    stream << "Default Double (with frac): " << 12.345 << Qt::endl;

    // ----------------------------------------------------
    // 2. 基数表示 (ShowBase) と大文字 (UppercaseBase, UppercaseDigits)
    // ----------------------------------------------------
    qDebug() << "\n--- 2. 基数表示と大文字 ---";
    // 16進数、8進数、2進数で基数を表示し、数字を大文字にします。
    stream.setNumberFlags(QTextStream::ShowBase | QTextStream::UppercaseBase | QTextStream::UppercaseDigits);

    // 16進数として出力するには、Qt::hex マニピュレータまたは setIntegerBase(16) が必要
    stream << Qt::hex; // 基数を16進数に設定
    printNumberWithFlags(stream, 255, "Hex (ShowBase, Uppercase)"); // 0XFF

    stream << Qt::oct; // 基数を8進数に設定
    printNumberWithFlags(stream, 64, "Oct (ShowBase)"); // 0100 (UppercaseBaseは8進数には影響しない)

    // Qt 6以降で利用可能な2進数出力 (Qt 5では直接のQTextStream::binマニピュレータはない場合があります)
    // 2進数出力は一般的にQString::number()でより柔軟に扱われますが、QTextStreamで制御する場合は setIntegerBase(2)
    stream.setIntegerBase(2); // 基数を2進数に設定
    printNumberWithFlags(stream, 10, "Binary (ShowBase)"); // 0B1010

    stream.setIntegerBase(10); // 基数を10進数に戻す

    // ----------------------------------------------------
    // 3. 符号の強制表示 (ForceSign)
    // ----------------------------------------------------
    qDebug() << "\n--- 3. 符号の強制表示 (ForceSign) ---";
    // 正の数にも '+' 符号を表示します。
    stream.setNumberFlags(QTextStream::ForceSign);
    printNumberWithFlags(stream, 100, "Signed Positive Int"); // +100
    printNumberWithFlags(stream, -50, "Signed Negative Int"); // -50

    // ----------------------------------------------------
    // 4. 小数点の強制表示 (ForcePoint)
    // ----------------------------------------------------
    qDebug() << "\n--- 4. 小数点の強制表示 (ForcePoint) ---";
    // 浮動小数点数で、小数点以下の桁が0でも常に小数点を表示します。
    stream.setNumberFlags(QTextStream::ForcePoint);
    // setRealNumberPrecision() も併用して表示桁数を調整できます
    stream.setRealNumberPrecision(2); // 小数点以下2桁を表示
    printDoubleWithFlags(stream, 123.0, "ForcePoint Double (0 frac)"); // 123.00
    printDoubleWithFlags(stream, 45.678, "ForcePoint Double (with frac)"); // 45.68 (精度設定により丸められる)

    stream.setRealNumberPrecision(-1); // デフォルトの精度に戻す

    // ----------------------------------------------------
    // 5. フラグの組み合わせと解除
    // ----------------------------------------------------
    qDebug() << "\n--- 5. フラグの組み合わせと解除 ---";
    // 既存のフラグを維持しつつ、新しいフラグを追加
    stream.setNumberFlags(stream.numberFlags() | QTextStream::ShowBase | QTextStream::UppercaseDigits);
    stream << Qt::hex; // 16進数に設定
    printNumberWithFlags(stream, 170, "Combined (ForceSign, ShowBase, UppercaseDigits)"); // +0XAA

    // 特定のフラグを解除 (ビット否定 ~ とビットAND & を使用)
    stream.setNumberFlags(stream.numberFlags() & ~QTextStream::ForceSign); // ForceSignを解除
    printNumberWithFlags(stream, 170, "ForceSign Removed (ShowBase, UppercaseDigits)"); // 0XAA

    // すべてのフラグを解除 (デフォルトに戻す)
    stream.setNumberFlags(QTextStream::NumberFlags()); // または QTextStream::reset() を使用
    printNumberWithFlags(stream, 99, "All Flags Removed"); // 99

    // ----------------------------------------------------
    // 6. QTextStream::reset() によるリセット
    // ----------------------------------------------------
    qDebug() << "\n--- 6. QTextStream::reset() によるリセット ---";
    stream.setNumberFlags(QTextStream::ShowBase | QTextStream::ForceSign | QTextStream::ForcePoint);
    stream << "Before reset: " << +0XFF << " " << 10.0 << Qt::endl;
    stream.reset(); // すべての書式設定フラグをリセット
    stream << "After reset: " << 255 << " " << 10.0 << Qt::endl;


    // 最終的な出力文字列を表示
    qDebug() << "\n--- 最終的な出力文字列 ---";
    qDebug() << outputString;

    return a.exec();
}

上記のコードを実行すると、以下のような出力(qDebug() による出力と、outputString の最終的な内容)が得られます。

qDebug() 出力 (実行中の情報)

--- QTextStream::numberFlags() の例 ---

--- 1. デフォルトの動作 ---

--- 2. 基数表示と大文字 ---

--- 3. 符号の強制表示 (ForceSign) ---

--- 4. 小数点の強制表示 (ForcePoint) ---

--- 5. フラグの組み合わせと解除 ---

--- 6. QTextStream::reset() によるリセット ---

--- 最終的な出力文字列 ---
"Default Int: 123\n"
"Default Negative Int: -45\n"
"Default Double (no frac): 789\n"
"Default Double (with frac): 12.345\n"
"Hex (ShowBase, Uppercase): 0XFF\n"
"Oct (ShowBase): 0100\n"
"Binary (ShowBase): 0B1010\n"
"Signed Positive Int: +100\n"
"Signed Negative Int: -50\n"
"ForcePoint Double (0 frac): 123.00\n"
"ForcePoint Double (with frac): 45.68\n"
"Combined (ForceSign, ShowBase, UppercaseDigits): +0XAA\n"
"ForceSign Removed (ShowBase, UppercaseDigits): 0XAA\n"
"All Flags Removed: 99\n"
"Before reset: +0XFF 10.00\n"
"After reset: 255 10\n"
  1. デフォルトの動作

    • 整数は符号なしで10進数。
    • 負の数は符号付き。
    • 浮動小数点数は、小数点以下が0の場合は小数点なし、それ以外はあり。
  2. 基数表示 (ShowBase) と大文字 (UppercaseBase, UppercaseDigits)

    • QTextStream::ShowBase により、16進数では 0X、8進数では 0、2進数では 0B のプレフィックスが付きます。
    • QTextStream::UppercaseBase により、プレフィックスの xb が大文字になります (0X, 0B)。
    • QTextStream::UppercaseDigits により、16進数の afAF と大文字になります (FF)。
    • 重要
      16進数で出力するには、stream << Qt::hex;stream.setIntegerBase(16); のように、基数を明示的に設定する必要があります。numberFlags() は出力形式を制御しますが、基数そのものを変更するものではありません。
  3. 符号の強制表示 (ForceSign)

    • QTextStream::ForceSign を設定すると、正の数にも + 符号が付きます (+100)。負の数には元々 - が付くので変化はありません。
  4. 小数点の強制表示 (ForcePoint)

    • QTextStream::ForcePoint を設定すると、789.0 のような小数点以下の桁が0の浮動小数点数でも、常に小数点とそれに続く桁(789.00)が表示されます。
    • setRealNumberPrecision(2) で小数点以下の桁数を2に設定しているため、123.0123.00 に、45.67845.68 に丸められています。
  5. フラグの組み合わせと解除

    • stream.setNumberFlags(stream.numberFlags() | QTextStream::ShowBase | QTextStream::UppercaseDigits); のように、既存のフラグを取得し、ビットOR演算 (|) を使って新しいフラグを追加するのが正しい方法です。
    • stream.setNumberFlags(stream.numberFlags() & ~QTextStream::ForceSign); のように、特定のフラグを解除するには、ビットAND演算 (&) とビット否定演算 (~) を組み合わせて使用します。
    • stream.setNumberFlags(QTextStream::NumberFlags()); で、すべてのカスタムフラグをクリアし、デフォルトの状態に戻せます。
  6. QTextStream::reset() によるリセット

    • stream.reset() を呼び出すと、numberFlags を含むすべての書式設定(フィールド幅、パディング文字、実数表記、精度など)がデフォルト値にリセットされます。これは、一度に多くの設定をデフォルトに戻したい場合に便利です。


QString::number()

これは、数値を QString に変換する際に最も基本的な方法です。様々なオーバーロードがあり、基数(10進数、16進数など)や浮動小数点数の精度などを指定できます。QTextStream の状態に依存しないため、特定の数値を単独でフォーマットしたい場合に非常に便利です。

特徴

  • 整数と浮動小数点数で異なるオーバーロードがある。
  • 個別の数値変換に特化しているため、シンプルで分かりやすい。
  • QTextStream の状態(設定されているフラグなど)に影響されない。


#include <QString>
#include <QDebug>

int main() {
    // 整数
    qDebug() << "Decimal:" << QString::number(123);
    qDebug() << "Hex (lowercase):" << QString::number(255, 16); // 16進数 (ff)
    qDebug() << "Hex (uppercase):" << QString::number(255, 16).toUpper(); // 16進数 (FF)
    qDebug() << "Binary:" << QString::number(10, 2); // 2進数 (1010)

    // 浮動小数点数
    qDebug() << "Double (default):" << QString::number(123.456); // 123.456
    qDebug() << "Double (fixed, 2 decimal places):" << QString::number(123.456, 'f', 2); // 123.46
    qDebug() << "Double (scientific, 3 decimal places):" << QString::number(12345.67, 'e', 3); // 1.235e+04
    qDebug() << "Double (general, 2 precision):" << QString::number(12.345, 'g', 2); // 12

    // 符号の強制表示(QString::number()自体には直接的なフラグはないため、条件分岐で対応)
    int val = 50;
    QString signedString = (val >= 0 ? "+" : "") + QString::number(val);
    qDebug() << "Signed:" << signedString; // +50

    return 0;
}

QString::arg() (書式文字列による置換)

QString::arg() は、printf-style の書式指定に似た、または Python の str.format() に近い柔軟な文字列置換機能を提供します。数値を文字列に埋め込む際に、フィールド幅、パディング、基数などを細かく制御できます。

特徴

  • 引数の型によって自動的に適切なオーバーロードが選択される。
  • フィールド幅、パディング文字、基数、浮動小数点数の表記形式(固定、科学、一般)、精度を引数で指定できる。
  • 複数の値を一度にフォーマットし、テンプレート文字列に埋め込むのに適している。


#include <QString>
#include <QDebug>

int main() {
    // 整数
    // %1 は最初の引数、d は10進数
    qDebug() << QString("Decimal: %1").arg(123); // Decimal: 123

    // 16進数、フィールド幅4、先頭ゼロ埋め、大文字
    // %L1 はローカライズされた大文字 (Qt 6以降のQString::arg()で利用可能)
    qDebug() << QString("Hex: %1").arg(255, 4, 16, QChar('0')).toUpper(); // Hex: 00FF

    // 符号付き、フィールド幅5、右寄せ
    qDebug() << QString("Signed: %+1").arg(100, 5, 10); // Signed:  +100
    qDebug() << QString("Signed: %+1").arg(-50, 5, 10);  // Signed:   -50

    // 浮動小数点数
    // f は固定小数点表記、.2 は小数点以下2桁
    qDebug() << QString("Double (fixed, 2 decimal): %1").arg(123.456, 0, 'f', 2); // Double (fixed, 2 decimal): 123.46

    // 科学表記、精度3
    qDebug() << QString("Double (scientific, 3 precision): %1").arg(12345.67, 0, 'e', 3); // Double (scientific, 3 precision): 1.235e+04

    // 複数の引数
    qDebug() << QString("Value 1: %1, Value 2 (hex): %2").arg(42).arg(255, 0, 16); // Value 1: 42, Value 2 (hex): ff

    return 0;
}

C++ 標準ライブラリ (<iomanip> と <format>)

Qtアプリケーションでも、C++標準ライブラリのフォーマット機能を使用できます。

<iomanip> (C++11/14/17 まで)

これは、std::cout などの std::ostream に適用するマニピュレータを提供します。QTextStream とは直接的な関係はありませんが、同じプログラム内で std::coutstd::stringstream を使ってフォーマットを行う場合に選択肢となります。

特徴

  • QTextStream::numberFlags() と同様に、ストリームの状態を変更するが、setw() などを除いてほとんどのマニピュレータは「sticky」(一度設定すると、リセットされるまでその状態が続く)。
  • std::hex, std::showbase, std::fixed, std::setprecision など。
  • std::ostream 系(std::cout, std::stringstream など)に適用される。


#include <iostream> // std::cout, std::endl
#include <iomanip>  // std::hex, std::showbase, std::setprecision, std::fixed, std::setfill, std::setw
#include <sstream>  // std::stringstream (文字列への出力)
#include <string>

int main() {
    std::stringstream ss;

    // 16進数、基数表示、大文字
    ss << std::hex << std::showbase << std::uppercase << 255 << std::endl; // 0XFF

    // 符号の強制表示
    ss << std::dec << std::showpos << 100 << " " << -50 << std::endl; // +100 -50

    // 小数点の強制表示、固定小数点表記、精度2
    ss << std::fixed << std::setprecision(2) << std::showpoint << 123.0 << " " << 45.678 << std::endl; // 123.00 45.68

    // フィールド幅と埋め文字
    ss << std::setfill('*') << std::setw(10) << 123 << std::endl; // *******123

    std::cout << ss.str();

    return 0;
}

<format> (C++20 以降)

C++20 で導入された <format> ライブラリは、Python の str.format() に非常に近い、現代的で安全、かつ強力な書式設定機能を提供します。これは今後のC++における文字列フォーマットの標準となるでしょう。

特徴

  • Qt 6.x 以降では、一部のQt型(QStringなど)に対する std::format のサポートが追加される可能性があり、よりシームレスになることが期待されます。
  • std::string を返すため、Qtの QString と組み合わせる場合は QString::fromStdString() を使う必要がある。
  • パフォーマンスも優れている。
  • 非常に柔軟な書式指定ミニ言語を持つ。
  • 型安全で、printf のような書式指定子のミスマッチによるバグを防ぐ。
#include <format> // C++20 以降
#include <iostream>
#include <string>
#include <QString> // Qtを使用する場合

int main() {
    // 整数
    std::string s1 = std::format("Decimal: {}", 123);
    std::string s2 = std::format("Hex (lowercase): {:x}", 255); // hex (ff)
    std::string s3 = std::format("Hex (uppercase): {:X}", 255); // HEX (FF)
    std::string s4 = std::format("Hex (with base): {:#x}", 255); // hex (0xff)
    std::string s5 = std::format("Binary (with base): {:#b}", 10); // binary (0b1010)

    // 符号の強制表示
    std::string s6 = std::format("Signed Positive: {:+}", 100); // +100
    std::string s7 = std::format("Signed Negative: {:+}", -50);  // -50

    // 浮動小数点数
    std::string s8 = std::format("Double (fixed, 2 decimal): {:.2f}", 123.456); // 123.46
    std::string s9 = std::format("Double (scientific, 3 precision): {:.3e}", 12345.67); // 1.235e+04
    std::string s10 = std::format("Double (force point, no frac): {:#.0f}", 789.0); // 789.
    std::string s11 = std::format("Double (general, 2 precision): {:.2g}", 12.345); // 12

    // フィールド幅と埋め文字
    std::string s12 = std::format("Padded: {:*>10}", 123); // *******123

    std::cout << s1 << "\n" << s2 << "\n" << s3 << "\n" << s4 << "\n"
              << s5 << "\n" << s6 << "\n" << s7 << "\n" << s8 << "\n"
              << s9 << "\n" << s10 << "\n" << s11 << "\n" << s12 << std::endl;

    // Qtアプリケーションでの使用例
    QString qtString = QString::fromStdString(std::format("Qt string from format: {}", 42));
    qDebug() << qtString;

    return 0;
}
  • C++標準ライブラリの機能を使いたい、またはC++20以降のモダンなフォーマットを使いたい場合
    <iomanip><format> を使用します。ただし、QString との相互変換が必要になる場合があります。特にC++20の <format> は、将来性も考えると非常に魅力的な選択肢です。

  • QTextStream でストリーム全体の設定を一括で制御したい場合
    QTextStream::setNumberFlags() や他の QTextStream の設定(setRealNumberPrecision(), setIntegerBase() など)が適しています。これは、ファイルやネットワークストリームなど、大量のデータを一貫したフォーマットで出力する際に特に有用です。

  • テンプレート文字列に複数の値を埋め込みたい場合
    QString::arg() が非常に強力で柔軟性があります。Qtの慣習にも合っています。

  • 簡単な数値変換や個別のフォーマット
    QString::number() が最もシンプルで直接的です。