规范的Unicode字符串形式

时间:2012-01-23 12:54:09

标签: c++ c unicode collation unicode-normalization

我将Unicode字符串编码为UTF8。 Unicode中的一个字符串可以包含少量字节表示。我想知道,是否有任何或可以创建任何规范(标准化)形式的Unicode字符串 - 所以我们可以例如将此类字符串与memcmp(3)等进行比较。例如ICU或任何其他C/C++库可以做到吗?

3 个答案:

答案 0 :(得分:6)

您可能正在寻找Unicode normalisation。基本上有四种不同的常规形式,每种形式都确保所有等效的字符串之后都有一个共同的形式。但是,在许多情况下,您还需要考虑区域设置,因此虽然这可能是进行字节到字节比较的廉价方法(如果您确保使用相同的Unicode转换格式,如UTF-8或UTF-16除了有限的用例之外,它不会给你带来太多的好处。

答案 1 :(得分:2)

比较Unicode代码点序列:

UTF-8本身就是规范表示。由相同的Unicode代码点组成的两个Unicode字符串将始终编码为完全相同的UTF-8字节序列,因此可以与memcmp进行比较。它是UTF-8编码的必要属性,否则不易解码。但我们可以更进一步,对于所有官方Unicode编码方案,UTF-8,UTF-16和UTF-32都是如此。它们将字符串编码为不同的字节序列,但它们始终将相同的字符串编码为相同的序列。如果考虑字节顺序和平台独立性,UTF-8是推荐的编码方案,因为在读取或写入16位或32位值时不必处理字节顺序。

所以答案是如果两个字符串使用相同的编码方案(例如UTF-8)和endiannes(它不是​​UTF-8的问题)编码,则生成的字节序列将是一样的。

比较Unicode字符串:

还有一个更难处理的问题。在Unicode中,某些字形(您在屏幕或纸张上看到的字符)可以用单个代码点或两个连续代码点(称为组合字符)的组合来表示。对于带有重音符号,变音符号等的字形通常都是如此。由于代码点表示不同,它们对应的字节序列会有所不同。在考虑这些组合字符时比较字符串不能通过简单的字节比较来执行,首先必须对其进行标准化。

其他答案提到了一些Unicode规范化技术,规范形式和库,可用于将Unicode字符串转换为其正常形式。然后,您将能够逐字节地与任何编码方案进行比较。

答案 2 :(得分:1)

您希望将字符串规范化为其中一种Unicode规范化表单。 libicu可以为您执行此操作,但不能在UTF-8字符串上执行此操作。您必须首先使用例如将其转换为UChar。 ucnv_toUChars,然后使用unorm_normalize进行规范化,然后使用ucnv_fromUChars转换回来。我认为还有一些特定版本的ucnv_ *用于UTF-8编码。

如果memcmp是你唯一的目标,你当然可以在unorm_normalize之后直接在UChar数组上这样做。