std::stringstream 在设置 UTF8 语言环境后被破坏

std::stringstream gets broken after setting UTF8 locale

提问人:Bogdan Ionitza 提问时间:4/11/2023 最后编辑:Bogdan Ionitza 更新时间:4/11/2023 访问量:130

问:

一旦我在 C++ 应用程序中设置了全局区域设置,我就无法输出数字。 下面是一个工作代码示例:

#include <locale>
#include <clocale>
#include <sstream>
#include <iostream>

void initLocale() {
    constexpr char locale_name[] = "en_US.UTF-8";
    std::setlocale( LC_ALL, locale_name );
    std::locale::global(std::locale(locale_name));
}

int main() {
    int64_t i = -123434534536;
    std::stringstream s1;
    s1 << i << "\n";
    std::cout << "Before locale: " << s1.str();
    
    initLocale();
    
    std::stringstream s2;
    s2 << i << "\n";
    std::cout << "After locale: " << s2.str();
    
    return 0;
}

我使用以下命令在 LINUX (debian) 上使用 g++ 编译此代码:

g++ -std=c++17 -o test test.cpp

我通过运行程序得到的输出是这样的:

Before locale: -123434534536
After locale: -123,434,534,536

为什么 std::stringstream 在设置语言环境后会表现得像这样,我该如何解决?

附言: 我需要使用此语言环境才能正确处理文件名中的非 ANSI 字符(我有一些包含中文字符的文件)

C++ UTF-8 标准 字符串流 setlocale

评论

0赞 molbdnilo 4/11/2023
这就是数字在美国区域设置中的格式。文件名与区域设置无关。(您是否将区域设置与字符编码混淆了?
0赞 Bogdan Ionitza 4/11/2023
@molbdnilo我知道这一点,但是设置此语言环境是正确处理文件名(长话短说)并打印到 stdout 的唯一方法。有没有办法只使用编码而不使用语言环境?

答:

2赞 Sam Varshavchik 4/11/2023 #1

libstdc++ 总是以这种方式实现语言环境,我也发现这很烦人。

最简单的解决方案是在格式化数值时显式灌输语言环境:"C"

std::stringstream s2;

s2.imbue(std::locale{"C"});
s2 << i << "\n";

根据所需的实际格式化输出操作,您可能会发现有必要使用填充的区域设置将所有格式化的整数输出隔离到自己的输出中,而其他所有内容都使用全局区域设置进行格式化。std::ostream"C"

评论

0赞 Bogdan Ionitza 4/11/2023
这似乎可以解决它,非常感谢!