24
4

4 回答 4

30

WideCharToMultiByte对指定字符集不支持的任何字符进行最佳匹配映射,包括剥离变音符号。您可以通过使用它并传递 20127 (US-ASCII) 作为代码页来完全按照您的意愿行事。

function BestFit(const AInput: AnsiString): AnsiString;
const
  CodePage = 20127; //20127 = us-ascii
var
  WS: WideString;
begin
  WS := WideString(AInput);
  SetLength(Result, WideCharToMultiByte(CodePage, 0, PWideChar(WS),
    Length(WS), nil, 0, nil, nil));
  WideCharToMultiByte(CodePage, 0, PWideChar(WS), Length(WS),
    PAnsiChar(Result), Length(Result), nil, nil);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   ShowMessage(BestFit('aÀàËëÇç–—€¢Š'));
end;

用你的例子调用它会产生你正在寻找的结果,包括 emdash-to-minus 的情况,我认为 Jeroen 的转换为规范化形式 D 的建议不会处理这种情况。如果你确实想采用这种方法,Michael Kaplan 有一篇博客文章明确讨论了剥离变音符号(而不是一般的规范化),但它使用 C# 和 Vista 中引入的 API。您可以使用 FoldString api(任何 WinNT 版本)获得类似的东西。

当然,如果您只为一个字符集执行此操作,并且您希望避免与 WideString 进行转换的开销,那么 Padu 是正确的,简单的 for 循环和查找表同样有效。

于 2009-12-12T05:33:34.263 回答
8

只是为了扩展克雷格对 Delphi 2009 的回答:

如果您使用 Delphi 2009 和更新版本,您可以使用更易读的代码,结果相同:

function OStripAccents(const aStr: String): String;
type
  USASCIIString = type AnsiString(20127);//20127 = us ascii
begin
  Result := String(USASCIIString(aStr));
end;

不幸的是,此代码仅适用于 MS Windows。在 Mac 上,重音不是由最合适的字符代替,而是由问号代替。

显然,Delphi 在 Windows 内部使用 WideCharToMultiByte,而在 Mac 上使用 iconv(参见 System.pas 中的 LocaleCharsFromUnicode)。问题是是否应该将不同操作系统上的这种不同行为视为错误并报告给 CodeCentral。

于 2013-03-19T12:52:50.267 回答
3

我相信你最好的选择是创建一个查找表。

于 2009-12-11T22:22:53.753 回答
1

您正在寻找的是标准化。

Michael Kaplan 写了一篇关于规范化的不错的博客文章

它不会立即解决您的问题,但会为您指明正确的方向。

——杰伦

于 2009-12-11T23:19:19.073 回答