西里尔字符 [使用 utf-8] 是 多字节 chars。您的十六进制“字符”是字符串/数组:
D0B1
所以,您不能使用%c 来检索它。你需要使用%s:
#include <stdio.h>
int
main(void)
{
char utf[1000];
char *cp;
scanf("%s", utf);
printf("%s\n", utf);
for (cp = utf; *cp != 0; ++cp)
printf(" %2.2X",*cp & 0xFF);
printf("\n");
return 0;
}
这是输出:
б
D0 B1
更新:
那么,这个 char 是如何在内存中定位的?当涉及到西里尔字母时,C 是否能够使 char 成为 2 字节?
首先,请参阅:https://en.wikipedia.org/wiki/UTF-8
当您通过键盘输入西里尔字符时,它是您的键盘硬件、终端仿真程序和文本编辑器的组合,可将键盘序列转换为utf-8 序列,最终出现在您正在输入的文本文件中编辑。
你所说的西里尔字符就是utf-8 所说的“代码点”。
当放置在文本文件中时,代码点变成如上所述的多字节序列。
scanf 和 printf 对此一无所知。例如,printf 只发送字符串:XXXXXXX\0,其中 X 可以是单个 ASCII 字符或多字符代码点的一部分。
由终端模拟器来理解这一点并从 utf-8 字体集中输出正确的字符 [其中包含西里尔字符、希腊字符、法语字符等]
strlen 和 strcpy 等函数仅关心尾随的 0x00 EOS 字符。因此,从技术上讲,它们可以工作并且通常可以像通过 ASCII 字符串一样轻松地传递 utf-8 字符串,因为 EOS 无论如何都是一样的。
但是,strlen 会给你字符串中char 的数量。例如,在上面的 strlen 将返回 2,因为它将 D0 和 B1 计算为 char 数组中的单独 char 值。
而且,strchr [可能] 不起作用。您可能希望使用strstr 代替utf-8。
当然,其中只有 一个 用于西里尔字符的代码点,因此utf-8 感知函数必须以不同的方式处理数组。比如在统计code point的个数的时候,他们需要看到D0B1是一个singlecode point,所以得到的count是one
一般规则是 ASCII (0x01-0x7F) 直接映射到 utf-8 作为单个 chars。任何具有高位 (0x80) 集的内容都是 utf-8 多字节代码点的一部分。 0x40 用于指示序列的开始 [最左边] 字节。序列中所有剩余字节的格式为(以位为单位):10xxxxxx。序列中剩余的字节数由起始字节中前缀 1 的位数表示。在下表中,它显示了如何解码字节序列(x 表示作为代码点值一部分的位):
# of Start Remaining Bytes
bytes Byte
1 0xxxxxxx
2 110xxxxx 10xxxxxx
3 1110xxxx 10xxxxxx 10xxxxxx
4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
因此,utf-8 感知函数可以在正向或反向扫描时检测并跳过代码点。并且,可以区分两个[或更多]相邻的多字节代码点。