首先,我使用ANSI C(不是C ++和任何非标准库,如MS CRT或glibc,......)开发一个独立的平台库。
经过几次搜索后,我发现ANSI C国际化的最佳方式之一是使用UTF-8编码。
在utf-8中:
但是当我想随机访问utf-8字符串的元素(字符)时,我遇到了一些问题。
在ASCII编码中:
char get_char(char* assci_str, int n)
{
// It is very FAST.
return assci_str[n];
}
以UTF-16/32编码:
wchar_t get_char(wchar_t* wstr, int n)
{
// It is very FAST.
return wstr[n];
}
这是我的UTF-8编码问题:
// What is the return type?
// Because sizeof(utf-8 char) is 8 or 16 or 24 or 32.
/*?*/ get_char(char* utf8str, int n)
{
// I can found Nth character of string by using for.
// But it is too slow.
// What is the best way?
}
感谢。
答案 0 :(得分:7)
也许你错误地想到了这一点。 UTF-8是一种编码,可用于序列化数据,例如将其写入文件或网络。但是,这是一个非常重要的编码,并且原始的Unicode代码点字符串最终可以包含任意数量的编码字节。
如果你想处理文本(给定你的描述),你应该做的是在内部存储原始,固定宽度的字符串。如果您要使用Unicode(您应该),那么每个代码点需要21位,因此最接近的整数类型为uint32_t
。简而言之,将所有字符串存储在内部作为整数数组。然后,您可以随机访问每个代码点。
只有在写入文件或控制台时才编码为UTF-8,并在读取时从UTF-8解码。
顺便说一句,Unicode代码点距离字符还有很长的路要走。角色的概念与高级别相比具有简单的一般机制。 (例如“a”+“重音坟墓” - 两个代码点,多少个字符?)
答案 1 :(得分:4)
你根本做不到。如果确实需要大量此类查询,则可以为UTF-8字符串构建索引,或者将其转换为UTF-32。 UTF-32是更好的内存表示,而UTF-8在磁盘上表现良好。
顺便说一下,您为UTF-16列出的代码也不正确。你可能想要照顾代理人物。
答案 2 :(得分:1)
你想要算什么?正如Kerrek SB所指出的,你可以有分解的字形,即“é”可以表示为单个字符(LATIN SMALL LETTER E WITH ACUTE
U + 00E9),或者表示为两个字符(LATIN SMALL LETER E
U + 0065 {{1 U + 0301)。 Unicode已经组成并分解了规范化形式。
您可能对计数感兴趣的不是字符,而是字形集群。你需要一些更高级别的库来处理这个问题,并处理规范化形式,适当的(依赖于语言环境)整理,正确的换行,正确的案例折叠(例如德国ß-> SS)适当的比迪支持等等......真正的I18N很复杂。
答案 3 :(得分:0)
与其他人所说的相反,我真的看不到使用UTF-32而不是UTF-8的好处:处理文本时,字形集群(或“用户感知字符”)比Unicode字符更有用(即原始码点),因此即使UTF-32也必须被视为可变长度编码。
如果您不想使用专用库,我建议使用UTF-8作为磁盘上,字节序无关的表示和修改的UTF-8(通过将零字符编码为两个而不同于UTF-8-字节序列)作为与ASCIIZ兼容的内存中表示。
可以在annex 29和character database中找到将字符串拆分为字素集群的必要信息。