混合UTF-16和ASCII字符串

时间:2013-07-31 01:40:10

标签: c encoding

我混合使用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]它会分割中文关键字并返回错误的结果。如何在没有任何其他库的情况下解决这个问题?

1 个答案:

答案 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--;
    }
}