【发布时间】:2017-04-27 17:18:30
【问题描述】:
如果您将 wchar_t、char16_t 或 char32_t 值提供给窄 ostream,它将打印代码点的数值。
#include <iostream>
using std::cout;
int main()
{
cout << 'x' << L'x' << u'x' << U'x' << '\n';
}
打印x120120120。这是因为basic_ostream 与其charT 的特定组合有一个operator<<,但其他字符类型没有类似的运算符,因此它们被静默转换为int 并以这种方式打印。类似地,非窄字符串文字(L"x"、u"x"、U"X")将被静默转换为void*并打印为指针值,非窄字符串objects(@ 987654338@, u16string, u32string) 甚至无法编译。
所以,问题是:在狭窄的 ostream 上打印wchar_t、char16_t 或 char32_t 值的最不可怕的方法是,作为字符,而不是作为代码点的数值?它应该正确地将在 ostream 的编码中可表示的 所有 个代码点转换为该编码,并在代码点不可表示时报告错误。 (例如,给定u'…' 和一个UTF-8 ostream,应该将三字节序列0xE2 0x80 0xA6 写入流;但给定u'â' 和一个KOI8-R ostream,应该报告错误。)
同样,如何在窄流上打印非窄 C 字符串或字符串对象,转换为输出编码?
如果这不能在 ISO C++11 中完成,我将采用特定于平台的答案。
(灵感来自this question。)
【问题讨论】:
-
简而言之,您必须 1) 使用宽 ostream,或 2) 自己将宽字符数据转换为窄编码(这可能是有损转换)。 ostream 无法为您进行转换。查看
std::wstring_convert,或使用ICONV 或ICU 之类的库。