C++11のto_string関数について調べていました。タイトルに書いたとおり、locale指定の影響と、書式の2つを知りたくなったためです。

このコードを動かしてみましょう。これは、Linux上のGCC 4.6.2 (glibc + libstdc++)で動かしました。

#include <iostream>
#include <string>
#include <locale>
#include <clocale>
#include <cstdio>
 
int main()
{
	double x = 1234.56;
 
	std::cout.imbue(std::locale::classic());
	std::setlocale(LC_ALL, "C");
	std::cout << "C:\n";
	std::cout << '\t' << x << '\n';
	std::cout << '\t' << std::to_string(x) << std::endl;
	std::printf("\t%f\n", x);
 
	std::cout.imbue(std::locale("ja_JP.UTF-8"));
	std::setlocale(LC_ALL, "ja_JP.UTF-8");
	std::cout << "ja_JP.UTF-8:\n";
	std::cout << '\t' << x << '\n';
	std::cout << '\t' << std::to_string(x) << std::endl;
	std::printf("\t%f\n", x);
 
	std::cout.imbue(std::locale("de_DE.UTF-8"));
	std::setlocale(LC_ALL, "de_DE.UTF-8");
	std::cout << "de_DE.UTF-8:\n";
	std::cout << '\t' << x << '\n';
	std::cout << '\t' << std::to_string(x) << std::endl;
	std::printf("\t%f\n", x);
}

こっちは、Windows上のVisual C++ 2010です。

#include <iostream>
#include <string>
#include <locale>
#include <clocale>
#include <cstdio>
 
int main()
{
	long double x = 1234.56;
 
	std::cout.imbue(std::locale::classic());
	std::setlocale(LC_ALL, "C");
	std::cout << "C:\n";
	std::cout << '\t' << x << '\n';
	std::cout << '\t' << std::to_string(x) << std::endl;
	std::printf("\t%f\n", x);
 
	std::cout.imbue(std::locale("jpn_jpn.932"));
	std::setlocale(LC_ALL, "jpn_jpn.932");
	std::cout << "jpn_jpn.932:\n";
	std::cout << '\t' << x << '\n';
	std::cout << '\t' << std::to_string(x) << std::endl;
	std::printf("\t%f\n", x);
 
	std::cout.imbue(std::locale("deu_deu.1252"));
	std::setlocale(LC_ALL, "deu_deu.1252");
	std::cout << "deu_deu.1252:\n";
	std::cout << '\t' << x << '\n';
	std::cout << '\t' << std::to_string(x) << std::endl;
	std::printf("\t%f\n", x);
 
	std::cout << std::endl;
}

なお、VC++版でlong doubleを使っている理由は、Visual C++ 2010の実装が不完全なためです(参考: [C++0X] std::to_string is non conforming | Microsoft Connect)。

de_DE/deu_deuは、Cやja_JP/jpn_jpnと小数点・桁区切りの記号が異なるロケールの代表例として選びました。

実行結果はそれぞれこうなりました。まずはLinux/GCC/libstdc++版です。

C:
        1234.56
        1234.560000
        1234.560000
ja_JP.UTF-8:
        1,234.56
        1234.560000
        1234.560000
de_DE.UTF-8:
        1.234,56
        1234,560000
        1234,560000

続いて、Visual C++版です。

C:
        1234.56
        1234.56
        1234.560000
jpn_jpn.932:
        1,234.56
        1234.56
        1234.560000
deu_deu.1252:
        1.234,56
        1234,56
        1234,560000

Visual C++はちょっと惜しいです。

printfの出力をわざわざ並べていることから分かったかもしれませんが、to_stringの結果はprintf系と同じ書式になるのが正しいようです。N3290(最終ドラフト)の21.5 Numeric conversions [string.conversions]のto_stringの欄には、型ごとにそれぞれ”%d”, “%u”, “%ld”, “%lu”, “%lld”, “%llu”, “%f”, “%f”, “%Lf”の書式でsprintfを呼んで文字列を作るというようなことが書いてあります。実は、その記述を見つけたので上記のプログラムを書いて試したという順序でした。

あとは、boost::lexical_castもついでに試しておけば良かったですね。次への課題とします。


スポンサード リンク

この記事のカテゴリ

  • ⇒ std::to_stringはlocale指定の影響を受けるのか、またどういう書式なのか気になった