以十六进制十六进制显示宽字符显示意外结果
Displaying wide character in hexadecimal hex shows unexpected result
我正在尝试以十六进制显示一个宽字符,它给了我意想不到的结果,它总是像 2 位十六进制和我的代码。
#include "stdlib.h"
#include "stdio.h"
#include"wchar.h"
#include "locale.h"
int main(){
setlocale(LC_ALL,"");
wchar_t ch;
wscanf (L"%lc",&ch);
wprintf(L"%x \n",ch);
return 0;
}
输入:Ω
结果:0xea
预期结果:0xcea9
我改了好几次setlocale
,但结果总是一样。
通知
当输入值小于 1 个字节时,它按预期工作。
请注意,您应该使用 <..>
来包含标准 headers。 wprintf("%x", ch)
行无效,因为它很可能是未定义的行为 - ch
(可能)不是 unsigned int
,您不能在其上应用 %x
。
您希望宽字符以 UTF-8 格式存储。好吧,那没有多大意义,他们不是。您的程序以 多字节编码 读取 序列 字节,然后将该字节序列转换(取决于语言环境)为宽字符编码。宽字符编码(通常)保持不变,在 linux 上应该是 UTF-32。语言环境会影响多字节字符与宽字符相互转换的方式,而不是宽字符的表示。
以下程序:
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(){
setlocale(LC_ALL,"");
wchar_t ch;
int cnt = wscanf(L"%lc",&ch);
if (cnt != 1) { /* handle error */ abort(); }
wprintf(L"%x\n", (unsigned int)ch);
return 0;
}
On linux 当输入 Greek Capital Letter Omega Ω U+3A9 程序输出 3a9
。实际发生的是终端读取UTF-8编码的字符,所以它读取两个字节0xCE 0xA9
,然后将它们转换为UTF-32并将结果存储在宽字符中.您可以将宽字符从宽字符编码 (UTF-32) 转换为多字节字符编码(UTF-8 应该是默认值,但取决于语言环境)并打印表示多字节字符编码中字符的字节:
char tmp[MB_CUR_MAX];
int len = wctomb(tmp, ch); // prefer wcrtomb
if (len < 0) { /* handle error */ abort(); }
for (int i = 0; i < len; ++i) {
wprintf(L"%hhx", (unsigned char)tmp[i]);
}
wprintf(L"\n");
这将在我的平台上输出 cea9
。
我正在尝试以十六进制显示一个宽字符,它给了我意想不到的结果,它总是像 2 位十六进制和我的代码。
#include "stdlib.h"
#include "stdio.h"
#include"wchar.h"
#include "locale.h"
int main(){
setlocale(LC_ALL,"");
wchar_t ch;
wscanf (L"%lc",&ch);
wprintf(L"%x \n",ch);
return 0;
}
输入:Ω
结果:0xea
预期结果:0xcea9
我改了好几次setlocale
,但结果总是一样。
通知
当输入值小于 1 个字节时,它按预期工作。
请注意,您应该使用 <..>
来包含标准 headers。 wprintf("%x", ch)
行无效,因为它很可能是未定义的行为 - ch
(可能)不是 unsigned int
,您不能在其上应用 %x
。
您希望宽字符以 UTF-8 格式存储。好吧,那没有多大意义,他们不是。您的程序以 多字节编码 读取 序列 字节,然后将该字节序列转换(取决于语言环境)为宽字符编码。宽字符编码(通常)保持不变,在 linux 上应该是 UTF-32。语言环境会影响多字节字符与宽字符相互转换的方式,而不是宽字符的表示。
以下程序:
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(){
setlocale(LC_ALL,"");
wchar_t ch;
int cnt = wscanf(L"%lc",&ch);
if (cnt != 1) { /* handle error */ abort(); }
wprintf(L"%x\n", (unsigned int)ch);
return 0;
}
On linux 当输入 Greek Capital Letter Omega Ω U+3A9 程序输出 3a9
。实际发生的是终端读取UTF-8编码的字符,所以它读取两个字节0xCE 0xA9
,然后将它们转换为UTF-32并将结果存储在宽字符中.您可以将宽字符从宽字符编码 (UTF-32) 转换为多字节字符编码(UTF-8 应该是默认值,但取决于语言环境)并打印表示多字节字符编码中字符的字节:
char tmp[MB_CUR_MAX];
int len = wctomb(tmp, ch); // prefer wcrtomb
if (len < 0) { /* handle error */ abort(); }
for (int i = 0; i < len; ++i) {
wprintf(L"%hhx", (unsigned char)tmp[i]);
}
wprintf(L"\n");
这将在我的平台上输出 cea9
。