c++ - std::locale::global 对 printf() 函数有影响吗?

标签 c++ locale printf std setlocale

我在我的电脑上使用俄语区域设置。
如果我设置:

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 语言环境设置?

<小时/>

感谢您的回答!
但是,C setlocale 函数对 C++ cout 对象有影响吗?

setlocale(LC_NUMERIC, "C");

这会影响通过 cout 打印十进制值吗?

最佳答案

当您设置全局 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 输出使用逗号小数,而C++ 输出仍然使用默认的句点小数符号。

C++ 1.2
C 1,2e+000

但是,设置 C++ 语言环境会影响 C 语言环境这一事实并不会使 C 语言环境像 C++ 语言环境那样可扩展。基于 C 语言环境的函数永远不会使用自定义 C++ 方面。相反,您必须依赖您的系统支持某些具有您所需功能的命名区域设置。

具体来说,std::locale::global() 被定义为使用您选择的 C++ 语言环境的名称来设置 C 语言环境(如果它有名称)。如果 C++ 语言环境没有名称,则行为由实现定义。此外,C++ 指定组合两个命名区域设置会生成一个命名区域设置。某些实现会生成有用的组合名称,允许您仅通过设置 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");

关于c++ - std::locale::global 对 printf() 函数有影响吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26390548/

相关文章:

c++ - QtConcurrent 与多线程的 QThread 的多线程性能

c++ - 我们可以使用 'malloced' 释放 'delete' 内存吗?

linux - 更改 Linux 中终端输出的语言

Python 语言环境不适用于 alpine linux

perl - 在 printf 中移动列?

C 编程 - 整数值打印不正确

PHP 或 CGI - 将 .ico 转换为 gif、png 或 jpg?

c++ - 如何检查 boost::fusion:at_key 的结果?

java - 使用 Java 重命名文件后,在 linux 系统上或通过 Java 无法访问某些文件

C printf 的行为很奇怪