printf输出不受全局语言环境的影响?

时间:2013-12-03 13:25:06

标签: c++ c visual-c++ internationalization locale

我无法在Visual-C ++(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: %s\n", 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: %d\n", i);
    printf("64 Bit integer output: %I64d\n", i64);
    _printf_l("32 Bit integer output: %d\n", /*locale=*/loc, i);
    _printf_l("64 Bit integer output: %I64d\n", /*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: %s\n", 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: %d\n", i);
    printf("64 Bit integer output: %I64d\n", i64);

    return 0;
}
<{3>} 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

4 个答案:

答案 0 :(得分:3)

我找到了IBM printf文档,其中说明语言环境会影响eEfgG个转化字符。

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

答案 1 :(得分:2)

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

  • C区域设置 包含有关千位分隔符的信息,但此信息为not used at all printf*系列函数(除非你计算flag extension ',这在MSVC中是不存在的)
  • C++语言环境也包含信息,iostreams 在格式化数字时实际使用numpunct facet
  • 使用C设置全局setlocale区域设置会影响C++

    设置的全局std::locale::global()区域设置
  • 获取格式化数字的正确代码最终为:

    static std::locale user_locale("");
    std::wstringstream buf; 
    buf.imbue(user_locale); 
    buf << some_integer; 
    
  • 对于某些用例,可以通过using the facet directly获得性能提升。

答案 2 :(得分:1)

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

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

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

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

答案 3 :(得分:0)

OP可能会从C中获取printf与BASH的printf混合(它有一些区域设置功能)??

(我在CrunchBang 11&#34; Waldorf&#34;来自Debian 7&#34; Wheezy&#34;)

LANG =的en_US.UTF-8
LC_NUMERIC未设置

例如:

$ printf "%d\n" 12345678
12345678
$ printf "%'d\n" 12345678
12,345,678

BASH printf command
(参见字段和打印修饰符)