如何在字符级别操作Unicode字符串?

时间:2012-10-15 14:26:48

标签: c++ winapi unicode

有时在角色级别操纵字符串是不可避免的。

这里我有一个为基于ANSI / ASCII的字符串编写的函数,它仅用LF替换CR / LF序列,并且还用LF替换CR。我们之所以使用它,是因为传入的文本文件通常会因为各种文本或电子邮件程序而导致混乱,因为各种文本或电子邮件程序使它们变得混乱,我需要它们采用一致的格式以使解析/处理/输出在未来正常工作。

这是一种相当有效的压缩实现,从各种行结束到LF,对于每个字符的单字节实现:

// returns the in-place conversion of a Mac or PC style string to a Unix style string (i.e. no CR/LF or CR only, but rather LF only)
char * AnsiToUnix(char * pszAnsi, size_t cchBuffer)
{
    size_t i, j;
    for (i = 0, j = 0; pszAnsi[i]; ++i, ++j)
    {
        // bounds checking
        ASSERT(i < cchBuffer);
        ASSERT(j <= i);

        switch (pszAnsi[i])
        {
            case '\n':
                if (pszAnsi[i + 1] == '\r')
                    ++i;
                break;

            case '\r':
                if (pszAnsi[i + 1] == '\n')
                    ++i;
                pszAnsi[j] = '\n';
                break;

            default:
                if (j != i)
                    pszAnsi[j] = pszAnsi[i];
        }

    }

    // append null terminator if we changed the length of the string buffer
    if (j != i)
        pszAnsi[j] = '\0';

    // bounds checking
    ASSERT(pszAnsi[j] == 0);

    return pszAnsi;
}

我正在尝试将其转换为可以使用多字节/ unicode字符串正常工作的内容,其中下一个字符的大小可以是多字节宽。

所以:

  1. 我只需要在有效的角色点(不在角色中间)查看角色。
  2. 我需要正确复制被拒绝作品一部分的角色(即复制整个字符,而不仅仅是字节)
  3. 我知道_mbsinc()会给我一个真实角色下一个开始的地址。但是什么是Unicode(UTF16)的等价物,并且已经存在能够复制完整字符的原语(例如length_character(wsz))?

2 个答案:

答案 0 :(得分:6)

关于UTF-8的一个好处是,如果你只关心ASCII子集,你的代码根本不需要改变。非ASCII字符被编码为多字节序列,其中所有字节都设置了高位,使它们本身不在ASCII范围内。您的CR / LF更换应该无需修改即可使用。

UTF-16具有相同的属性。可以编码为单个16位实体的字符永远不会与需要多个实体的字符冲突。

答案 1 :(得分:2)

不要试图将内部文本保持在任何编码的混合中,并与那些真正的地狱一起工作。

首先选择一些“内部”编码。当目标平台是UNIX时,那么UTF-8是很好的候选者,在那里显示稍微容易一些。当目标平台是Windows时,UTF-16是很好的候选者,Windows无论如何都在内部使用它。无论你选择什么,坚持只有它。

然后将所有传入的“脏”文本转换为该编码。您也可以进行一些实际看起来与您的代码完全相同的重新格式化,只有在包含UTF-16的wchar_t的情况下,您必须使用L'\n'这样的文字。