在Delphi中更改数组中的特殊字符

6

我获取到的某些字符串是UTF-8编码的,包含一些特殊字符,比如Å¡、Ä‘、Ä等。我正在使用StringReplace()将其转换为普通文本,但我只能转换一种类型的字符。因为PHP也有一个替换字符串的函数,可以支持数组,如此处所示:如何在PHP中用基于的字符替换特殊字符?

<?php
  $vOriginalString = "¿Dónde está el niño que vive aquí? En el témpano o en el iglú. ÁFRICA, MÉXICO, ÍNDICE, CANCIÓN y NÚMERO.";

  $vSomeSpecialChars = array("á", "é", "í", "ó", "ú", "Á", "É", "Í", "Ó", "Ú", "ñ", "Ñ");
  $vReplacementChars = array("a", "e", "i", "o", "u", "A", "E", "I", "O", "U", "n", "N");

  $vReplacedString = str_replace($vSomeSpecialChars, $vReplacementChars, $vOriginalString);

  echo $vReplacedString; // outputs '¿Donde esta el nino que vive aqui? En el tempano o en el iglu. AFRICA, MEXICO, INDICE, CANCION y NUMERO.'
?>

我该如何在Delphi中实现这个功能?StringReplace不支持数组。

该字符串采用UTF-8编码,并且包含“特殊字符”?什么是“特殊字符”?如果您可以访问iconv,请查看此答案 - Kerrek SB
如果您想进行比较,则可以在dwCmpFlags中至少使用NORM_IGNORENONSPACE,并使用CompareString - NGLN
2个回答

6
function str_replace(const oldChars, newChars: array of Char; const str: string): string;
var
  i: Integer;
begin
  Assert(Length(oldChars)=Length(newChars));
  Result := str;
  for i := 0 to high(oldChars) do
    Result := StringReplace(Result, oldChars[i], newChars[i], [rfReplaceAll])
end;

如果您担心由StringReplace引起的所有不必要的堆分配,那么可以按照以下方式编写它:
function str_replace(const oldChars, newChars: array of Char; const str: string): string;
var
  i, j: Integer;
begin
  Assert(Length(oldChars)=Length(newChars));
  Result := str;
  for i := 1 to Length(Result) do
    for j := 0 to high(oldChars) do
      if Result[i]=oldChars[j] then
      begin
        Result[i] := newChars[j];
        break;
      end;
end;

请按照以下方式调用:

newStr := str_replace(
  ['á','é','í'],
  ['a','e','i'], 
  oldStr
);

@Thalvik 为了节省你的一些工作,这里有一个完整的数组(我相信还有其他的)。 - NGLN

6

去除口音的过程被称为规范化

由于您正在使用Unicode,因此您不仅想要规范化问题中的少量重音字符。实际上,您正在寻找Unicode 规范化形式 D(NFD)或KD(NFKD),您可以在Windows和当然在Delphi中完成。

这个答案应该让您了解理论方面。

这段Delphi代码这个答案应该让您开始实现。


这听起来像是正确的方法。我只是天真地回答了问题。 - David Heffernan
抱歉,“去除重音符号”并不是规范化——它只是去除了重音符号!规范化不会改变字符的语义,它只是以一致的方式在“基本加附加符号”和“遗留的Latin-1”形式之间选择(如果适用,则选择其他形式),以便如果它们在语义上相等,则两个规范化的字符串比较相等。OP的目标似乎是将文本转换为仅包含ASCII字符的形式。 - Kerrek SB
@Kerrek:我推测规范化,因为原帖链接到PHP解决方案并提到了规范化。 - Jeroen Wiert Pluimers
1
@Jeroen:即使链接的SO答案是正确的,正如其评论中所指出的那样;PHP规范化函数恰好执行Unicode标准和我所说的内容。它没有把ä转换成a! - Kerrek SB
@Jeroen:嗯,我更喜欢使用iconv将其转换为ASCII//TRANSLIT,然后用正则表达式去掉\w,我认为这样更简单和更可靠... - Kerrek SB
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接