vmo*_*eco 6 c encoding printf widechar
我试图理解printf如何使用宽字符(wchar_t).
我做了以下代码示例:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
wchar_t *s;
s = (wchar_t *)malloc(sizeof(wchar_t) * 2);
s[0] = 42;
s[1] = 0;
printf("%ls\n", s);
free(s);
return (0);
}
Run Code Online (Sandbox Code Playgroud)
输出:
*
Run Code Online (Sandbox Code Playgroud)
这里一切都很好:我的字符(*)被正确显示.
我想展示另一种角色.在我的系统上,wchar_t似乎编码为4个字节.所以我试着显示以下字符:
É
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
wchar_t *s;
s = (wchar_t *)malloc(sizeof(wchar_t) * 2);
s[0] = 0xC389;
s[1] = 0;
printf("%ls\n", s);
free(s);
return (0);
}
Run Code Online (Sandbox Code Playgroud)
但这次没有输出,我尝试使用"编码"部分(参见上一个链接)中的许多值s[0](0xC389,201,0xC9)...但我从未得到过É显示的字符.我也试过%S而不是%ls.
如果我尝试像这样调用printf:printf("<%ls>\n", s)打印的唯一字符是'<',显示被截断.
为什么我有这个问题?我应该怎么做?
Tim*_*Tim 10
请务必检查errno并返回值printf!
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
int main(void)
{
wchar_t *s;
s = (wchar_t *) malloc(sizeof(wchar_t) * 2);
s[0] = 0xC389;
s[1] = 0;
if (printf("%ls\n", s) < 0) {
perror("printf");
}
free(s);
return (0);
}
Run Code Online (Sandbox Code Playgroud)
看输出:
$ gcc test.c && ./a.out
printf: Invalid or incomplete multibyte or wide character
Run Code Online (Sandbox Code Playgroud)
首先,C程序的默认语言环境C(也称为POSIX)仅限ASCII.您将需要加入到呼叫setlocale,具体setlocale(LC_ALL,"").
如果你的LC_ALL,LC_CTYPE或者LANG环境变量设置为允许UTF-8空白时,你必须明确地选择一个区域.setlocale(LC_ALL, "C.UTF-8")适用于大多数系统 - C是标准的,通常实现UTF-8子集C.
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>
int main(void)
{
wchar_t *s;
s = (wchar_t *) malloc(sizeof(wchar_t) * 2);
s[0] = 0xC389;
s[1] = 0;
setlocale(LC_ALL, "");
if (printf("%ls\n", s) < 0) {
perror("printf");
}
free(s);
return (0);
}
Run Code Online (Sandbox Code Playgroud)
看输出:
$ gcc test.c && ./a.out
?
Run Code Online (Sandbox Code Playgroud)
打印出错误字符的原因是因为wchar_t表示宽字符(例如UTF-32),而不是多字节字符(例如UTF-8).请注意,wchar_tGNU C库中总是32位宽,但C标准并不要求它.如果使用UTF-32BE编码(即0x000000C9)初始化字符,则它会正确打印出来:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>
int main(void)
{
wchar_t *s;
s = (wchar_t *) malloc(sizeof(wchar_t) * 2);
s[0] = 0xC9;
s[1] = 0;
setlocale(LC_ALL, "");
if (printf("%ls\n", s) < 0) {
perror("printf");
}
free(s);
return (0);
}
Run Code Online (Sandbox Code Playgroud)
输出:
$ gcc test.c && ./a.out
É
Run Code Online (Sandbox Code Playgroud)
请注意,您还可以LC通过命令行设置(语言环境)环境变量:
$ LC_ALL=C.UTF-8
$ ./a.out
É
Run Code Online (Sandbox Code Playgroud)