printf输出不受全局区域设置的影响

printf output not affected by global locale?

本文关键字:设置 影响 区域 全局 输出 printf      更新时间:2023-10-16

我无法在VisualC++(VS 2005)中获得printf函数来输出整数中的数千分隔符。

注:注释表明这是printf的正常行为。然而,C++iostream确实将千位分隔符插入数字中(使用std::stringstreamimbue进行了测试),所以这纯粹是iostream的一个功能,并且不存在于"C"格式化函数中吗?

这是测试代码:

    setlocale(LC_ALL, ""); // -> User locale
    _locale_t loc = _create_locale(LC_ALL, ""); // -> user locale for *_l version
    struct lconv *pLocalSettings = localeconv();
    printf("Locale is: %sn", setlocale(LC_NUMERIC, NULL));
    printf("Thousands separator set to : {%s}n", pLocalSettings->thousands_sep);
    printf("Grouping set to: {%o}n", int(pLocalSettings->grouping[0]));
    int i = 1000000;
    __int64 i64 = i * 2;
    printf("32 Bit integer output: %dn", i);
    printf("64 Bit integer output: %I64dn", i64);
    _printf_l("32 Bit integer output: %dn", /*locale=*/loc, i);
    _printf_l("64 Bit integer output: %I64dn", /*locale=*/loc, i64);
    _free_locale(loc);

输出为:

Locale is: German_Austria.1252
Thousands separator set to : {.}
Grouping set to: {3}
32 Bit integer output: 1000000
64 Bit integer output: 2000000
32 Bit integer output: 1000000
64 Bit integer output: 2000000

经过进一步检查,它似乎不是这样工作的。我试过这个:

#include <iostream>
#include <clocale>
using namespace std;
int main() {
    setlocale(LC_ALL, "en_US"); // -> User locale
    struct lconv *pLocalSettings = localeconv();
    printf("Locale is: %sn", setlocale(LC_NUMERIC, NULL));
    printf("Thousands separator set to : {%s}n", pLocalSettings->thousands_sep);
    printf("Grouping set to: {%o}n", int(pLocalSettings->grouping[0]));
    int i = 1000000;
    long long  i64 = i * 2;
    printf("32 Bit integer output: %dn", i);
    printf("64 Bit integer output: %I64dn", i64);
    return 0;
}

在http://www.compileonline.com/compile_cpp11_online.php(在那里找不到永久链接。)

输出为:

Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
Locale is: en_US
Thousands separator set to : {,}
Grouping set to: {3}
32 Bit integer output: 1000000
64 Bit integer output: 2000000

让我分享我在这里学到的东西:

  • C语言环境确实包含有关千位分隔符的信息,printf*函数族根本不使用该信息(除非计算MSVC中不存在的标志扩展'
  • C++区域设置也包含信息,iostreams实际上在格式化数字时使用了该信息(numpunct方面)
  • 使用setlocale设置全局C区域设置不会影响std::locale::global() 设置的全局C++区域设置

  • 获取我的格式化号码的正确代码最终是:

    static std::locale user_locale("");
    std::wstringstream buf; 
    buf.imbue(user_locale); 
    buf << some_integer; 
    
  • 对于某些用例,可以通过直接使用facet来获得性能加速。

我找到了IBM printf文档,其中说区域设置会影响eEfgG转换字符。

od都不使用区域设置转换。。。

在《标准C库》一书的第90-93页,p.J.Plauger展示了一个名为_Fmtval()的函数的代码,该函数使用localeconv()提供的信息格式化浮点值。调用方指定该值的格式是国际货币、本地货币、整数还是具有指定小数位数的浮点。部分代码处理数字分组和分隔符的插入。这可以作为编写自己函数的指南。

同一作者在以下链接上的文章提供了与本书类似的讨论,并提供了几乎相同的_Fmtval()版本。不幸的是,文章提供的代码似乎包含一些OCR错误。如果可能的话,请参阅这本书。

标准C:格式化货币价值,p.J.Plauger

http://www.drdobbs.com/standard-c/184402377?pgno=4

OP可能是从C中获得printf与BASH的printf混合在一起(它确实有一些区域设置功能)??

(我在CrunchBang 11《华尔道夫》上,源自Debian 7《Wheezy》)

LANG=en_US.UTF-8
LC_NUMERIC未设置

例如:

$ printf "%dn" 12345678
12345678
$ printf "%'dn" 12345678
12,345,678

BASH printf命令
(请参阅字段和打印修改器)