【发布时间】:2020-02-17 04:07:24
【问题描述】:
我试图弄清楚 C 如何处理 Unicode 中的字符代码。我将我的语言环境设置为 LC_ALL "fr_CA.UTF8" 然后输入一个带有wscanf() 的字符(作为wchar_t 的数组...)。然后我探索每个 byte 并发现一些奇怪的东西。我输入了 U+1d11e 的高音键(“????”从网页复制)。这实际上是 3 个字节,所以我预计会有 2 个wchar_t。我得到:0x1e、0xd1、0x00、0x00,最后两个是空结尾字符。这是我的代码:
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
int main ( int argc, char* argv[] )
{
setlocale( LC_ALL, "fr_CA.utf8" );
wchar_t input[256];
wscanf( L"%ls", input);
wprintf( L"%ls\n", input );
wprintf( L"Length = %d\n", wcslen( input ) );
wprintf( L"%d\n", (int)(input[0]&0x00ff) );
wprintf( L"%d\n", (int)((input[0]&0xff00)>>8) );
wprintf( L"%d\n", (int)(input[1]&0x00ff) );
wprintf( L"%d\n", (int)((input[1]&0xff00)>>8) );
wprintf( L"%d\n", (int)(input[2]&0x00ff) );
wprintf( L"%d\n", (int)((input[2]&0xff00)>>8) );
return 0;
}
我的期望是有 0x1e、0xd1、0x01、0x00、0x00、0x00...
但我有 0x1e、0xd1、0x00、0x00...
让我着迷的是wprintf( L"%ls\n", input ); 实际上正确地打印了高音键......那么什么可以区分字符 U+1D11E 和 U+D11E?
另外,我在 Kubuntu 16.04 LTS 的 Konsole 中运行我的程序,并使用 gcc 6.5.0 编译它...如果重要的话。
【问题讨论】:
-
会不会是您根本没有打印第三个字节? This cleaned up program 为
printf ???? | a输出???? Length = 1 1D11E -
所以首先要做的是确定 wchar_t 的大小。
-
呃... ????在记事本中保存到 UTF8 给了我字节
F09D849E。 UTF8 是一个扩展系统,因此它的数据之间有控制位,这意味着您无法手动读取这些内容unless you know how,并且它通常最终会比 unicode 符号的值长。通过将上述值转换为二进制并去除控制位来解码上述值,得到以下结果:11110[000] 10[011101] 10[000100] 10[011110]=>00001 11010001 00011110=1D11E。 -
@ikegami 看来你是对的。
-
@Nyerguds 我知道数据位中有控制位。