在 C 中打印宽字符文字

Printing wide character literals in C

我正在尝试使用 wchar.h header 中定义的 wchar_t 类型将 unicode 打印到终端 linux。我尝试了以下方法:

#include <wchar.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  /*
  char* direct = "\xc2\xb5";

  fprintf(stderr, "%s\n", direct);
  */

  wchar_t* dir_lit = L"μ";
  wchar_t* uni_lit = L"\u03BC";
  wchar_t* hex_lit = L"\xc2\xb5";

  fwprintf(stderr,
           L"direct: %ls, unicode: %ls, hex: %ls\n",
           dir_lit,
           uni_lit,
           hex_lit);

  return 0;
}

并使用 gcc -O0 -g -std=c11 -o main main.c 编译它。 这会产生输出 direct: m, unicode: m, hex: ?u(基于带有 LANG=en_US.UTF-8 的终端)。十六进制:

00000000  64 69 72 65 63 74 3a 20  6d 2c 20 75 6e 69 63 6f  |direct: m, unico|
00000010  64 65 3a 20 6d 2c 20 68  65 78 3a 20 3f 75 0a     |de: m, hex: ?u.|
0000001f

我设法获得 μ 所需输出的唯一方法是通过上面注释的代码(作为 char* 由十六进制数字组成)。

我也试过基于wcstombs功能打印:

void print_wcstombs(wchar_t* str)
{
  char buffer[100];

  wcstombs(buffer, str, sizeof(buffer));

  fprintf(stderr, "%s\n", buffer);
}

例如,如果我调用 print_wcstombs(dir_lit),则根本不会打印任何内容,因此这种方法似乎根本不起作用。

原则上我会与十六进制数字解决方案抗衡,但是,字符串的长度计算不正确(应该是一个,但是是两个字节长),所以通过 printf 格式化不会正常工作。

有什么方法可以按照我打算使用 wchar_t 类型的方式处理/打印 unicode 文字吗?

用你的程序as-is,我编译并运行得到

direct: ?, unicode: ?, hex: ?u

然后我包含 <locale.h> 并在 main() 函数的最开头添加了一个 setlocale(LC_CTYPE, "");,当 运行 使用 Unicode 语言环境时(LANG=en_US.UTF-8), 产生

direct: μ, unicode: μ, hex: µ

(代码点 0xC2 在 Unicode 中是 Â,0xB5 是 µ(U+00B5 MICRO SIGN 与 U+03BC GREEK SMALL LETTER MU 相对);因此 'hex' 输出中看到的字符;结果可能会有所不同如果使用不对宽字符使用 Unicode 的环境)。

基本上,要输出宽字符,您需要设置 ctype 语言环境,以便 stdio 系统知道如何将它们转换为底层系统期望的多字节字符。


更新程序:

#include <wchar.h>
#include <stdio.h>
#include <locale.h>

int main(int argc, char *argv[])
{
   setlocale(LC_CTYPE, "");

  wchar_t* dir_lit = L"μ";
  wchar_t* uni_lit = L"\u03BC";
  wchar_t* hex_lit = L"\xc2\xb5";

  fwprintf(stderr,
           L"direct: %ls, unicode: %ls, hex: %ls\n",
           dir_lit,
           uni_lit,
           hex_lit);

  return 0;
}