【问题标题】:wcout not writing wide character out to command promptwcout 没有将宽字符写入命令提示符
【发布时间】:2011-04-21 23:29:06
【问题描述】:

我正在尝试在 Windows 命令提示符中写出以下字符:ュ (U+FF6D)。

我可以看到使用 WriteConsoleW 写出的字符。如果我使用 CP_ACP 代码页(chcp 返回 932:日语)使用 WideCharToMultiByte,我也可以看到该字符。但是,当我尝试在 WriteConsoleW 成功打印的同一字符串上使用常规 wcout 时,它会窒息。

当我执行 setlocale(LC_ALL, "") 时,它会打印 English_UnitedStates.1252(我安装时的默认代码页)。

为什么在其他人成功时 wcout 却失败了?

注意:我重新启动机器以将其系统区域设置更改为日本日语

【问题讨论】:

  • 您是否曾经致电std::wcout.imbue() 更改wcout 的代码页?
  • 那行得通。但是为什么当我重置系统区域设置时 wcout 的代码页不同?发表解释,您可以获得简单的分数。

标签: c++ windows internationalization


【解决方案1】:

C++ iostreams 的默认语言环境始终是“C”语言环境。来自 C++03 标准,§27.4.2.3/4:

locale getloc() const;

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

来自 §22.1.1.2/1-2:

locale() throw();

默认构造函数:当前全局语言环境的快照。

构造最后传递给locale::global(locale&)的参数的副本,如果它已被调用;否则,生成的构面具有与locale::classic() 相同的虚函数语义。

从 §22.1.1.5/4-6:

static const locale& classic();

“C”语言环境。

返回:实现经典“C”语言环境语义的语言环境,相当于值locale("C")

注意:此语言环境、它的方面及其成员函数不会随时间而改变。

由于std::coutstd::wcout 具有静态存储持续时间,它们保证在调用main 之前被初始化,因此在应用程序启动时总是具有“C”语言环境;即,没有足够早的时间来调用locale::global 并更改std::coutstd::wcout 的默认语言环境。因此,如果您想使用非默认代码页,则必须始终自己灌输全局流。

【讨论】:

  • 所以我想这是一个特定于 Windows 的问题。我从来没有在我的应用程序中调用 cout.imbue,但是它仍然可以处理代码页字符。我假设(是的,假设是邪恶的事情)wcout 会灌输相同的语言环境。
【解决方案2】:

wcoutmain 中的任何代码执行之前创建。当你打电话给setlocale 时,wcout 已经在那里,准备好了。它不会尝试跟踪您可能使用setlocale 进行的后续更改,因此它会继续使用默认值而不是您使用setlocale 设置的任何内容。

【讨论】:

  • 好的,这是有道理的,但是如果我的机器使用能够打印字符 (U+FF6D) 的语言环境启动,则映射字符到 CP 932。我想我的问题是如何是否定义了 wcout 的默认语言环境?
  • @bogertron :我的回答解决了这个问题。
猜你喜欢
  • 2020-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
  • 2017-06-22
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多