2

我有一个Delphi 7应用程序,我在其中处理 ANSI 字符串,我需要计算它们的字符数(而不是字节数)。我总是知道与字符串关联的字符集(以及代码页)。

因此,知道字符集(代码页)后,我目前正在使用MultiByteToWideChar它来获取字符数。当字符集是中文、韩文或日文字符集之一时,它很有用,其中大多数字符的长度为 2 个字节,并且简单地使用该Length函数不会给我想要的东西。

但是,它仍然将复合字符计为两个字符,我需要将它们计为一个。现在,一些复合字符在 Unicode 中具有预先组合的版本,由于MB_PRECOMPOSED默认使用 ,因此这些字符将被正确计为一个字符。但是许多字符根本不作为预先组合存在,例如希伯来语、阿拉伯语、泰语等中的字符,这些字符被计为两个。

所以问题真的是:如何将复合字符计为单个字符?MultiByteToWideChar我不介意将 ANSI 字符串转换为宽字符串来计算字符数,反正我已经在这样做了。

4

1 回答 1

2

您可以像这样计算 Unicode 代码点:

function CodePointCount(P: PWideChar): Integer;
var
  Count: Integer;
begin
  Count := 0;
  while Word(P^)<>0 do
  begin
    if (Word(P^)>=$D800) and (Word(P^)<=$DFFF) then
      // part of surrogate pair
      inc(Count)
    else 
      inc(Count, 2);
    inc(P);
  end;  
  Result := Count div 2;
end;

这涵盖了您没有提到的问题。即 UTF-16 是一种可变宽度编码。

但是,这不会告诉您 UTF-16 字符串表示的字形数量。那是因为一些代码点代表组合字符。这些组合字符与其相邻字符组合以形成单个等效字符。因此,多个代码点,单个字形。更多信息可以在这里找到:http ://en.wikipedia.org/wiki/Unicode_equivalence

这是更难的问题。要解决它,您的代码需要完全理解每个 Unicode 代码点的含义。它是一个组合字符吗?它是如何结合的?你真的需要一个专用的 Unicode 库。比如ICU。

我给你的另一个建议是放弃使用 ANSI 代码页。如果您真的关心国际化,那么您需要使用 Unicode。

于 2014-02-20T13:48:50.577 回答