【发布时间】:2011-08-31 18:07:45
【问题描述】:
如何将单个 UTF-8 字符映射到其在 C 中的 unicode 点?
[例如,È 将映射到 00c8]。
【问题讨论】:
如何将单个 UTF-8 字符映射到其在 C 中的 unicode 点?
[例如,È 将映射到 00c8]。
【问题讨论】:
如果您平台的 wchar_t 存储 unicode(如果它是 32 位类型,它可能会存储)并且您有 UTF-8 语言环境,您可以调用 mbrtowc(来自 C90.1)。
mbstate_t state = {0};
wchar_t wch;
char s[] = "\303\210";
size_t n;
memset(&state, 0, sizeof(state));
setlocale(LC_CTYPE, "en_US.utf8"); /*error checking omitted*/
n = mbrtowc(&wch, s, strlen(s), &state);
if (n <= (size_t)-2) printf("%lx\n", (unsigned long)wch);
为了更灵活,可以调用iconv接口。
char s[] = "\303\210";
iconv_t cd = iconv_open("UTF-8", "UCS-4");
if (cd != -1) {
char *inp = s;
size_t ins = strlen(s);
uint32_t c;
uint32_t *outp = &c;
size_t outs = 0;
if (iconv(cd, &inp, &ins, &outp, &outs) + 1 >= 2) printf("%lx\n", c);
iconv_close(cd);
}
【讨论】:
iconv_t cd = iconv_open("UTF-8", "UCS-2");。
iconv 标头文档中提到了“UCS-*”。我错过了(我尝试了很多其他组合)。您的回答正是我们所需要的,谢谢。
一些值得看的东西:
【讨论】:
iconv 是为了改变编码,而不是为了映射到字符串的表示。也许我错过了一些明显的东西。
UTF-8 到 UCS-2 转换器的相当快速的实现。 BMP 之外的代理和字符作为练习。
该函数返回从输入s 字符串消耗的字节数。负值表示错误。
生成的 unicode 字符被放在p 指向的地址处。
int utf8_to_wchar(wchar_t *p, const char *s)
{
const unsigned char *us = (const unsigned char *)s;
p[0] = 0;
if(!*us)
return 0;
else
if(us[0] < 0x80) {
p[0] = us[0];
return 1;
}
else
if(((us[0] & 0xE0) == 0xC0) && (us[1] & 0xC0) == 0x80) {
p[0] = ((us[0] & 0x1F) << 6) | (us[1] & 0x3F);
#ifdef DETECT_OVERLONG
if(p[0] < 0x80) return -2;
#endif
return 2;
}
else
if(((us[0] & 0xF0) == 0xE0) && (us[1] & 0xC0) == 0x80 && (us[2] & 0xC0) == 0x80) {
p[0] = ((us[0] & 0x0F) << 12) | ((us[1] & 0x3F) << 6) | (us[2] & 0x3F);
#ifdef DETECT_OVERLONG
if(p[0] < 0x800) return -2;
#endif
return 3;
}
return -1;
}
【讨论】:
s 视为unsigned char*,但即便如此,我还是得到0xe201c for “ (\U{201c})。
0xe2 << 12 溢出了 16 位字,结果是 0x2000 而不是 0xe2000 字。