HOWTO · C++
C++ でフロートを文字列に変換する方法
この記事では、C++ で float を文字列に変換する方法を示します。
このページの内容
実行時の浮動小数点値を手早く文字列にするには std::to_string、書式を細かく指定するには文字列ストリーム、API が文字配列を必要とする場合は snprintf を使います。プリプロセッサによる文字列化は別の処理で、ソースコード上のトークンをテキストにするものです。プログラムの実行中に計算された値を参照することはできません。
手早く変換するには std::to_string を使う
<string> の std::to_string は浮動小数点値を受け取り、std::string を返します。既定の書式で問題がない基本的な表示やログ出力に便利です。実際の書式結果は C++ ライブラリやそのバージョンによって異なる場合があるため、どのツールチェーンでも同じ小数表記になるとは限りません。
次の例を実行します。
コード例と、実行時に表示されるテキストは英語のままです。
#include <iostream>
#include <string>
int main() {
double value = 12.5;
std::string text = std::to_string(value);
std::cout << text << '\n';
}
文字列に含まれるのは書式化されたテキストであり、value に格納された値が変わるわけではありません。選択した小数書式で十分な桁数が表示されない場合、ごく小さな値がゼロとして表示されることがあります。小数点以下の桁数が重要なら、既定の表記で必要な情報が保たれると決めつけず、書式を明示して選んでください。
文字列ストリームで小数の書式を指定する
使い慣れたストリーム書式制御を使いたい場合は、<sstream> の std::stringstream を利用します。std::fixed を指定すると精度は小数点以下の桁数を表し、<iomanip> の std::setprecision でその桁数を設定できます。std::fixed を指定しない場合、ストリームの精度は異なる意味になり、有効桁数を制御します。
コード例と、実行時に表示されるテキストは英語のままです。
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
int main() {
double value = 12.34567;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << value;
std::string text = stream.str();
std::cout << text << '\n';
}
str() は文字列を値として返します。C 形式の文字ポインターが必要なら、その文字列を有効な状態で保持してください。std::string text = stream.str(); の後に const char* ptr = text.c_str(); とすれば、text が存在し変更されない間、文字データを利用できます。stream.str() が返す一時オブジェクトから c_str() を取得し、その式の評価後もポインターを保持してはいけません。一時オブジェクトは式の終わりに破棄されます。
マクロでコンパイル時定数を文字列化する
プリプロセッサの文字列化演算子 # は、マクロ引数として記述されたトークンを文字列リテラルにします。ソースコード中の定数には使えますが、実行時の浮動小数点値を変換したり、数値を書式化したりするものではありません。単純なマクロでは、引数がマクロ名でも、その名前が書かれたとおりに文字列化されます。2 段階のマクロを使うと、先にその名前を展開できます。
コード例と、実行時に表示されるテキストは英語のままです。
#include <iostream>
#define STRINGIZE_INNER(x) #x
#define STRINGIZE(x) STRINGIZE_INNER(x)
#define RATE 2.75
int main() {
const char* text = STRINGIZE(RATE);
std::cout << text << '\n';
}
結果は展開後のソースコード上のトークンを表します。float の実行時変換ではなく、マクロでは丸め、小数点以下の桁数の指定、ロケールに応じた書式化もできません。
snprintf で文字バッファに書式化する
C API がサイズ上限のある文字配列を必要とする場合は、<cstdio> の snprintf を選びます。バッファの容量を渡し、戻り値を確認してください。負の値は書式化の失敗を示し、戻り値が容量以上ならテキスト全体は収まりません。容量が 0 より大きければ、テキストが切り詰められた場合もバッファはヌル終端されます。
コード例と、実行時に表示されるテキストは英語のままです。
#include <cstddef>
#include <cstdio>
#include <iostream>
int main() {
double value = 12.34567;
char buffer[32];
int result = std::snprintf(buffer, sizeof buffer, "%.2f", value);
if (result < 0) {
std::cout << "Formatting failed\n";
} else if (static_cast<std::size_t>(result) >= sizeof buffer) {
std::cout << "Buffer too small\n";
} else {
std::cout << buffer << '\n';
}
}
書式 %.2f は、小数点以下 2 桁を指定します。結果を使う前に snprintf の戻り値を確認し、完全なテキストが収まっているか判断してください。容量を指定できず、出力先配列の範囲を超えて書き込むおそれのある上限なしの sprintf は避けてください。
用途に応じて変換方法を選ぶ
実行時の値を手早く変換するなら、まず std::to_string を使います。小数の書式を明示する必要がある場合は、std::fixed と std::setprecision を組み合わせた文字列ストリームを使ってください。マクロによる文字列化は、必要なテキストがコンパイル時のトークンから得られる場合に限り、C 形式の上限付きバッファへの出力には snprintf を選びます。どの方法でも、数値とそのテキスト表現を区別してください。書式によって表示内容は決まりますが、元の浮動小数点値は変わりません。