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

How does one manipulate Unicode strings at the character level?

本文关键字:操作 Unicode 字符串 字符      更新时间:2023-10-16

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

这里我有一个为基于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] = '';
// bounds checking
ASSERT(pszAnsi[j] == 0);
return pszAnsi;
}

我正试图将其转换为能够正确处理多字节/unicode字符串的内容,其中下一个字符的大小可以是多字节宽。

因此:

  1. 我需要只在有效字符点(不在字符中间)查看字符
  2. 我需要正确地复制被拒绝部分的字符部分(即复制整个字符,而不仅仅是字节)

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

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

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

不要试图将文本内部混合使用任何编码,并使用那些真正的编码。

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

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