在 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;
}
我正在尝试使用 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;
}