我试图弄清楚C如何处理Unicode中的字符代码。我将语言环境设置为LC_ALL“ fr_CA.UTF8”,然后输入一个字符wscanf()(作为wchar_t... 的数组)。然后,我探索每个字节,发现一些奇怪的地方。我输入了一个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;
}
Run Code Online (Sandbox Code Playgroud)
我的期望是拥有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编译了它……如果有关系的话。
如果您wchar_t正确地打印了组成值的字节,或者只是跳过了它并打印了它们的值而没有尝试将它们分解为字节,则会看到您期望的结果:
wprintf(L"%x\n", (int)input[0]);
wprintf(L"%x\n", (int)input[1]);
Run Code Online (Sandbox Code Playgroud)
输出将是:
1d11e
0
Run Code Online (Sandbox Code Playgroud)
您尝试执行此操作的方式表明,您误以为wchar_t值是16位,并且存在“多wchar_t字符” 之类的东西。C语言非常明确,没有这样的东西。16位的实现wchar_t是错误的(或者至少不能在BMP之外支持Unicode)。当然,一个颇受欢迎的错误是严重错误的。
我刚刚注意到您在问题标题中也提到了UTF-8,但是内容与UTF-8表示无关。wchar_t是(通常;并非完全必需)Unicode编码点编号,它等效于UCS-4(或在仅支持BMP的实现中为UCS-2)。为了使您能够访问该字符,几乎可以肯定的是,语言环境的多字节编码必须为UTF-8(尽管GB18030也可以使用),但是如果要处理所有宽度的流,则不会出现UTF-8字符流。
| 归档时间: |
|
| 查看次数: |
77 次 |
| 最近记录: |