错误的Unicode转换,如何在Delphi 2010源代码中存储重音字符并处理字符集?

DiG*_*iGi 7 delphi unicode character-encoding

我们正在将项目从Delphi 2006升级到Delphi 2010.旧代码是:

InputText: string;
InputText := SomeTEditComponent.Text;
...
for i := 1 to length(InputText) do
if InputText[i] in ['0'..'9', 'a'..'z', '?' { and more special characters } ] then ...
Run Code Online (Sandbox Code Playgroud)

问题是重音字母 - 比较会失败.

我尝试将源代码从ANSI切换到UTF8和LE UCS-2,但没有运气.仅作为AnsiChar投射:

if CharInSet(AnsiChar(InputText[i]), ['0'..'9', 'a'..'z', '?']) then
Run Code Online (Sandbox Code Playgroud)

有趣的是Delphi如何处理这些字母 - 在调试期间在Evaluate中尝试这个:

Ord('?') = Ord('Ø')
Run Code Online (Sandbox Code Playgroud)

(是的,Delphi说True,在Windows 7上捷克语)


问题是:如何在不强制它们作为AnsiStrings的情况下存储和比较简单字符串?因为如果这不起作用我们为什么要使用Unicode?

谢谢大家的回复

现在我们在一些部分使用简单的CharInSet(AnsiChar(...

Uwe*_*abe 5

宣言CharInSet

function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean; overload; inline;
function CharInSet(C: WideChar; const CharSet: TSysCharSet): Boolean; overload; inline;
Run Code Online (Sandbox Code Playgroud)

而TSysCharSet是

TSysCharSet = set of AnsiChar;
Run Code Online (Sandbox Code Playgroud)

因此CharInSet只能与一组AnsiChar进行比较.这就是为什么你的重音字符转换为AnsiChar.

没有等同于set of WideChar集合限制为256个元素.你必须实现一些其他方法来检查角色.

就像是

const
  specials: string = '?';

if CharInSet(InputText[i], ['0'..'9', 'a'..'z']) or (Pos(InputText[I], specials) > 0) then 
Run Code Online (Sandbox Code Playgroud)

可能是一个尝试.您可以specials根据需要添加更多字符.


Cos*_*und 2

正如 Uwe Raabe 所提到的,Unicode 字符的问题是它们非常大。如果 Delphi 允许您创建一个“Char 集”,那么它的大小将是 8 Kb!一个“AnsiChar 集合”只有 32 个字节大小,非常易于管理。

\n\n

我想提供一些替代方案。第一个是 CharInSet 函数的一种直接替代,它使用 CHAR 数组来执行测试。它唯一的优点是几乎可以从任何地方立即调用它,但它的好处也仅限于此。如果可以的话我会避免这种情况:

\n\n
function UnicodeCharInSet(UniChr:Char; CharArray:array of Char):Boolean;\nvar i:Integer;\nbegin\n  for i:=0 to High(CharArray) do\n    if CharArray[i] = UniChr then\n    begin\n      Result := True;\n      Exit;\n    end;\n  Result := False;\nend;\n
Run Code Online (Sandbox Code Playgroud)\n\n

这个函数的问题是它不处理x in [\'a\'..\'z\']语法而且速度很慢!这些替代方案速度更快,但并不像人们想要的那样接近直接替代品。第一组要研究的替代方案是Microsoft 的字符串函数。其中有 IsCharAlpha 和 IsCharAlphanumeric,它们可能会解决很多问题。这些问题的问题是,所有“alpha”字符都是相同的:您最终可能会得到非英语非捷克语言中的有效 Alpha 字符。或者,您可以使用Embarcadero 中的 TCharacter 类- 实现全部在 Character.pas 单元中,并且看起来很有效,我不知道 Microsoft 的实现有多有效。

\n\n

另一种选择是编写自己的函数,使用“case”语句来使事情正常工作。这是一个例子:

\n\n
function UnicodeCharIs(UniChr:Char):Boolean;\nvar i:Integer;\nbegin\n  case UniChr of\n    \'\xc4\x83\': Result := True;\n    \'\xc5\x9f\': Result := False;\n    \'\xc4\x82\': Result := True;\n    \'\xc5\x9e\': Result := False;\n    else Result := False;\n  end;\nend;\n
Run Code Online (Sandbox Code Playgroud)\n\n

我检查了为此函数生成的汇编程序。虽然 Delphi 必须为此实现一系列“if”条件,但它做得非常有效,比从代码中实现一系列 IF 语句要好得多。但它还需要很多改进。

\n\n

对于经常使用的测试,您可能需要寻找一些基于位掩码的实现。

\n