1

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

在这里,我有一个为基于 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. 我需要正确复制被拒绝部分的字符部分(即复制整个字符,而不仅仅是字节)

我知道 _mbsinc() 会给我一个真实字符的下一个开始的地址。但是 Unicode (UTF16) 的等价物是什么,是否已经存在能够复制完整字符的原语(例如 length_character(wsz))?

4

2 回答 2

6

UTF-8 的一大优点是,如果您只关心 ASCII 子集,那么您的代码根本不需要更改。非 ASCII 字符被编码为多字节序列,其中所有字节都设置了高位,使它们本身不在 ASCII 范围内。您的 CR/LF 替换无需修改即可工作。

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

于 2012-10-15T14:35:46.163 回答
2

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

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

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

于 2012-10-15T14:58:52.020 回答