以下代码有效:
char *text = "中文";
printf("%s", text);
然后,我尝试通过它的Unicode代码点来打印此文本,该代码点的“中”是0x4e2d
,而“文”是0x6587
:
当然,什么也没打印出来。
我试图了解将多字节字符串存储到char*
中并如何使用unicode代码点打印多字节字符串时发生的情况,并且, “ Format specifier '%ls' requires 'wchar_t *' argument instead of 'wchar_t *'
是什么意思?
感谢您的帮助。
编辑: 我在Mac OSX(高Sierra 10.13.6)上运行
$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
答案 0 :(得分:3)
wchar_t *arr = malloc(2 * sizeof(wchar_t)); arr[0] = 0x4e2d; arr[1] = 0x6587;
首先,以上字符串不是以空值结尾的。 printf
函数知道数组的开始,但是不知道数组的结尾或数组的大小。您必须在末尾添加一个零来制作以N结尾的C字符串。
要打印此以空值结尾的宽字符串,请在基于Unix的计算机(包括Mac)上使用"printf("%ls", arr);"
,在Windows中使用"wprintf("%s", arr);"
(这是完全不同的事情,它实际上将字符串视为UTF16)。
对于基于Unix的计算机,请确保添加setlocale(LC_ALL, "C.UTF-8");
或setlocale(LC_ALL, "");
。
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "C.UTF-8");
//print single character:
printf("%lc\n", 0x00004e2d);
printf("%lc\n", 0x00006587);
printf("%lc\n", 0x0001F310);
wchar_t *arr = malloc((2 + 1)* sizeof(wchar_t));
arr[0] = 0x00004e2d;
arr[1] = 0x00006587;
arr[2] = 0;
printf("%ls\n", arr);
return 0;
}
放在一边
在UTF32中,代码点始终需要4个字节(示例0x00004e2d
),可以用4个字节的数据类型char32_t
(或POSIX中的wchar_t
)表示。
在UTF8中,代码点需要1、2、3或4个字节。 ASCII字符的UTF8编码需要一个字节。 中
需要3个字节(或3个char
值)。您可以通过运行以下代码来确认这一点:
printf("A:%d 中:%d :%d\n", strlen("A"), strlen("中"), strlen(""));
例如,我们不能在UTF8中使用单个char
。我们可以改用字符串:
const char* x = u8"中";
我们可以在C中使用普通的字符串函数,例如strcpy
等。但是某些标准C函数不起作用。例如,strchr
不能找到中
。这通常不是问题,因为诸如“打印格式说明符”之类的字符全为ASCII且为一个字节。