c++ - iostreams - 打印 `wchar_t` 或 `charXX_t` 值作为字符

标签 c++ iostream widechar

如果你输入 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*并打印为指针值,非窄字符串对象(wstringu16stringu32string)甚至无法编译。

所以,问题是:打印 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/

相关文章:

c++ - Linux 中的电源管理通知

c++ - 错误 : name followed by '::' must be a class or namespace name

java - 如何在 Java 窗口的 windowClosing 事件中关闭套接字或 I/O 流?

c++ - Good() 和 fail() 的理解

C标准: L prefix and octal/hexadecimal escape sequences

c++ - 具有可参数化 "zero"的稀疏矩阵类

c++ - Qt:无法从 javascript 调用共享对象方法/属性

c++ - 从 scanf 和 cin 获取变量

c++ - 宽阔的溪流和炭

c - glibc 中的 fxprintf.c 中如何将多字节字符串转换为宽字符字符串?