如果你输入 wchar_t
, char16_t
, 或 char32_t
value 到一个窄的 ostream,它将打印代码点的数值。
#include <iostream>
using std::cout;
int main()
{
cout << 'x' << L'x' << u'x' << U'x' << '\n';
}
打印 x120120120
.这是因为有一个 operator<<
对于basic_ostream
的具体组合及其 charT
, 但其他字符类型没有类似的运算符,因此它们会自动转换为 int
并以这种方式打印。同样,非窄字符串文字( L"x"
、 u"x"
、 U"X"
)将被静默转换为 void*
并打印为指针值,非窄字符串对象(wstring
、u16string
、u32string
)甚至无法编译。
所以,问题是:打印 wchar_t
的最不糟糕的方法是什么? , char16_t
, 或 char32_t
窄 ostream 上的值,作为字符,而不是代码点的数值?它应该正确地将 ostream 编码中可表示的所有代码点转换为该编码,并且当代码点不可表示时应报告错误。 (例如,给定 u'…'
和一个 UTF-8 ostream,三字节序列 0xE2 0x80 0xA6 应该写入流;但是给定 u'â'
和一个 KOI8-R ostream,应该报告错误。)
同样,如何在窄 ostream 上打印非窄 C 字符串或字符串对象,并转换为输出编码?
如果这不能在 ISO C++11 中完成,我将采用特定于平台的答案。
(灵感来自 this question 。)
最佳答案
如您所述,没有 operator<<(std::ostream&, const wchar_t)
对于狭窄的 ostream。如果你想使用语法,你可以教 ostream
如何处理 wchar
s 以便该例程被选为比需要首先转换为整数的例程更好的重载。
如果你喜欢冒险:
namespace std {
ostream& operator<< (ostream& os, wchar_t wc) {
if(unsigned(wc) < 256) // or another upper bound
return os << (unsigned char)wc;
else
throw your_favourite_exception; // or handle the error in some other way
}
}
否则,做一个简单的struct
透明地包含 wchar_t
并且有一个自定义 friend operator<<
并在输出之前将宽字符转换为宽字符。
编辑:要与语言环境进行即时转换,您可以使用 <cwchar>
中的函数,比如:
ostream& operator<< (ostream& os, wchar_t wc) {
std::mbstate_t state{};
std::string mb(MB_CUR_MAX, '\0');
size_t ret = std::wcrtomb(&mb[0], wc, &state);
if(ret == static_cast<std::size_t>(-1))
deal_with_the_error();
return os << mb;
}
不要忘记将您的语言环境设置为系统默认值:
std::locale::global(std::locale(""));
std::cout << L'ŭ';
关于c++ - iostreams - 打印 `wchar_t` 或 `charXX_t` 值作为字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41107667/