8

PCでロシア語のロケール設定を使用しています。
私が設定する場合:

class numpunct_withpoint: public numpunct<char>
{
protected:
    /// Override the function that gives the decimal separator.
    char do_decimal_point() const
    {
        return '.';
    }
};
...
locale loc(std::locale::classic(), new numpunct_withpoint);
std::locale::global(loc);


そしてより

printf("%f", 3.14);

出力は次のとおりです。

3,14

小数点記号は「、」であり、do_decimal_point関数とは異なります。C ++ロケールで小数点記号のCロケール設定を変更するにはどうすればよいですか?


ご回答ありがとうございます!
しかし、Csetlocale関数はC++ coutオブジェクトに影響を与えますか?

setlocale(LC_NUMERIC, "C");

これは、coutを介して10進値を印刷するときに影響しますか?

4

2 に答える 2

7

グローバル C++ ロケールを設定すると、C ロケールも変更されます。C ロケールを変更しても、グローバル C++ ロケール変更されません。

以下は、C++ グローバル ロケールの設定を示しています。

#include <cstdio>
#include <clocale>
#include <fstream>

int main() {
    const char * locale_name = "French_France.1252"; // or "fr_Fr.UTF-8" on Unix
    double value = 1.2;

    std::locale::global(std::locale(locale_name));

    std::ofstream("out.txt") << "C++ " << value << '\n';

    if (FILE *f = std::fopen("out.txt", "a")) {
        std::fprintf(f, "C %1.1e\n", value);
        std::fclose(f);
    }
}

C と C++ の両方の出力で、コンマ小数点を使用する必要があります。

C++ 1,2
C 1,2e+000

C++ ロケールの設定を C ロケールの設定に置き換えるとstd::setlocale(LC_ALL, locale_name);、出力が変更され、C 出力のみがコンマ 10 進数を使用し、C++ 出力では引き続きデフォルトのピリオド小数点記号が使用されるようになります。

C++ 1.2
C 1,2e+000

ただし、C++ ロケールの設定が C ロケールに影響するという事実は、C ロケールが C++ ロケールのように拡張可能になるわけではありません。カスタム C++ ファセットは、C ロケール ベースの関数では使用されません。代わりに、必要な機能を持つ名前付きロケールをサポートするシステムに依存する必要があります。

具体的にstd::locale::global()は、名前がある場合、選択した C++ ロケールの名前を使用して C ロケールを設定するように定義されています。C++ ロケールに名前がない場合、動作は実装定義です。また、C++ は、2 つの名前付きロケールを結合すると名前付きロケールが生成されることを指定します。一部の実装では、C++ ロケールを設定するだけで C ロケール カテゴリを混在させることができる便利な結合名が生成されます。

std::locale::global(std::locale(std::locale("ru_RU"), "C", std::locale::numeric));

libstdc++ を使用すると、次の名前のロケールが生成されます。

LC_CTYPE=ru_RU;LC_NUMERIC=C;LC_TIME=ru_RU;LC_COLLATE=ru_RU;LC_MONETARY=ru_RU;LC_MESSAGES=ru_RU;LC_PAPER=ru_RU;LC_NAME=ru_RU;LC_ADDRESS=ru_RU;LC_TELEPHONE=ru_RU;LC_MEASUREMENT=ru_RU;LC_IDENTIFICATION=ru_RU LC_CTYPE=ru_RU ;LC_NUMERIC=C;LC_TIME=ru_RU;LC_COLLATE=ru_RU;LC_MONETARY=ru_RU;LC_MESSAGES=ru_RU;LC_PAPER=ru_RU;LC_NAME=ru_RU;LC_ADDRESS=ru_RU;LC_TELEPHONE=ru_RU;LC_MEASUREMENT=ru_RU;LC_IDENTIFICATION=ru_RU

そのため、C ロケールは、C++ ロケールと同じ「ru_RU」ロケールと「C」ロケールの混合に設定されます。

残念ながら、他の実装では、技術的には準拠しているものの、あまり有用でない動作が選択されます。Visual Studio で

std::locale::global(std::locale(std::locale("Russian_Russia.1251"), "C", std::locale::numeric));

「C」という名前のロケールを生成します。そのため、C++ ロケールはロシア語と C ロケール カテゴリの適切な混合ですが、C ロケールは単純に「C」に設定されています。したがって、これらのプラットフォームで C ロケール カテゴリを混在させるには、C ロケールを直接設定する必要があります。

// set the C++ locale first
std::locale::global(std::locale(std::locale("Russian_Russia.1251"), "C", std::locale::numeric));

// set the C locale second, because it will not overwrite the changes you made to the C++ locale
std::setlocale(LC_ALL, "Russian_Russia.1251");
std::setlocale(LC_NUMERIC, "C");
于 2012-09-11T16:28:52.327 に答える
0

C ライブラリは、C++ と同じロケール設定を使用しません。で使用されるロケールをオーバーライドするには、 setlocaleprintfを使用します。

setlocale(LC_NUMERIC, "POSIX");

または類似。

于 2012-09-11T15:42:04.530 に答える