【问题标题】:wchar_t output with libc++使用 libc++ 输出 wchar_t
【发布时间】:2021-08-21 22:37:39
【问题描述】:
#include <locale>
#include <iostream>

int main()
{
    std::locale::global(std::locale("en_US.utf8"));
    std::wcout << L"Həł£ō שøяļđ\n";
    return 0;
}

这在 libstdc++(gcc 和 clang)中按预期工作,但在 libc++ 中只打印第一个字符(恰好是 ASCII)。我在 Gentoo Linux 上使用 libcxx-0.0_p20140322。

这是 libc++ 中的一个已知错误,还是只是我不知道如何烹饪?

更新1。我试过了

std::locale::global(std::locale("en_US.utf8"));
std::locale::global(std::locale(""));
std::setlocale(LC_ALL, "en_US.utf8");
std::setlocale(LC_ALL, "");

它们都做同样的事情。

更新 2。为简单起见,此处提供了宽字符串文字。当以任何其他方式获取字符串(从 UTF-8 转换,从二进制文件读取,...)时,也会发生同样的事情

【问题讨论】:

  • 试试在开头加std::setlocale(LC_CTYPE, "");
  • 注意:编译器不需要支持在我们的源代码中嵌入这些字符(源字符集不同于执行字符集) ,并且您的语言环境设置只是运行时的事情,它不会影响编译器处理此字符串的方式。尝试使用 C++11 unicode 字符串文字? (甚至可以通过\uNNNNN 代码指定字符)
  • 标准 C++ 只有两个已知的语言环境:C 语言环境和用户的默认语言环境。另一个问题是旧的 g++ 只尊重 C 库的语言环境 IIRC。因此,Kerrek 建议调用 setlocale(更改 C 库的语言环境)可能正是我们所需要的。
  • @KerrekSB 查看更新。
  • @MattMcNabb 查看更新。

标签: c++ clang++ libc++


【解决方案1】:

您必须显式地为输出流注入语言环境,如下所示:

std::wcout.imbue(std::locale());

这使事情按预期工作。事实上,这是标准要求的

27.5.3.3 ios_base 函数

locale getloc() const;

4 如果没有注入语言环境,则全局 C++ 语言环境的副本 locale() 在构建时生效。

所以当wcout 被构造时,它会得到一个包含在其中的初始语言环境的副本。初始语言环境是“C”。我的错误假设是没有明确灌输语言环境的流总是使用当前的全局语言环境(而不仅仅是在构建时)。稍加思考,这个假设是完全不合理的。

2021 年 6 月编辑:所以理论上 imbue 应该可以工作,但实际上它在 libstdc++ 中不起作用。需要为此设置全局语言环境,这可能是一个 libstdc++ 错误。灌输适用于其他宽字符流,但不适用于 std::wcout

【讨论】:

    猜你喜欢
    • 2012-10-05
    • 1970-01-01
    • 2013-10-29
    • 1970-01-01
    • 2015-08-18
    • 2013-10-23
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多