我混合使用ASCII和UTF-16字符串,主要问题是,我需要以某种方式将其拆分为字符串中的每个字符。 例如,假设我们在Windows下并且(在大多数情况下)默认编码是UTF-16:
const wchar_t msg[] = L"AД诶B";
我已经定义了4个字符。
A = 2 bytes.
Д = 2 bytes.
诶 = 4 bytes.
B = 2 bytes.
我需要从字符串中获取第4个字符(ASCII B),但是如果我使用msg [4]它会分割中文关键字并返回错误的结果。如何在没有任何其他库的情况下解决这个问题?
答案 0 :(得分:3)
正如您已经发现的那样,UTF-16实际上是一种可变宽度编码。因此,您必须扫描字符串以执行准确的字符索引。
幸运的是,很容易判断一个字符是否是多字序列的一部分:UTF-16中唯一的多字序列(如当前定义的那样)是代理对:一个字在范围[D800-DBFF]后跟[DC00-DFFF]范围内的字。因此,当您遇到这样的序列时,请将其视为单个字符。
这可能适合您的需求:
UChar32 utf16_char_at_index(const wchar_t *s, off_t index) {
while(1) {
if(s[0] >= 0xd800 && s[0] <= 0xdbff) {
/* First half of surrogate pair; check next half */
if(s[1] >= 0xdc00 && s[1] <= 0xdfff) {
/* surrogate pair: skip or return */
if(index == 0) {
return ((s[0] - 0xd800) << 10) | (s[1] - 0xdc00);
}
s += 2;
index--;
continue;
}
/* Otherwise, decoding error...may want to flag error here */
}
if(index == 0) {
return s[0];
}
s++;
index--;
}
}