解决E2010不兼容的类型:' AnsiChar'和' Char'

时间:2014-03-23 16:19:09

标签: delphi delphi-xe5

我尝试将一些代码从D2007转换为XE5并获得

E2010不兼容的类型:'AnsiChar'和'Char'

来自此代码

  TSetOfChar = Set of Char;

  var
    CharacterSet: TSetOfChar;
    s: String;

    for j := 1 to Length(s) do
    begin
      Include(CharacterSet, s[j]);  // Error E2010
      if not CaseSensitive then
      begin
        Include(CharacterSet, AnsiUpperCase(s[j])[1]);  // Error E2010
        Include(CharacterSet, AnsiLowerCase(s[j])[1])   // Error E2010
      end
    end;

有任何解决方案的建议吗?我认为这足以处理AnsiStrings。

2 个答案:

答案 0 :(得分:2)

Delphi集的基本类型最多可包含256个元素。这意味着您的集合实际上是set of AnsiChar

您的代码失败,因为AnsiUpperCase(s[j])的类型为string UnicodeString。因此,AnsiUpperCase(s[j])[1]的类型为char,即WideChar。这是编译器试图告诉你的内容。尽管名称如此,AnsiUpperCaseAnsiLowerCase仍然有效,并返回UnicodeString

如果您确实仍想使用ANSI字符串,则需要使用AnsiUpperCase单元中的AnsiLowerCaseAnsiStrings函数。这些版本运行,并返回AnsiString。将该单元添加到uses子句中,并确保传递AnsiString值:

var
  AnsiStr: AnsiString;
....
AnsiStr := AnsiString(s);
for j := 1 to Length(AnsiStr) do
begin
  Include(CharacterSet, AnsiStr[j]); 
  if not CaseSensitive then
  begin
    Include(CharacterSet, AnsiUpperCase(AnsiStr[j])[1]);  
    Include(CharacterSet, AnsiLowerCase(AnsiStr[j])[1])   
  end
end;

当然,创建包含单个字符的字符串似乎效率极低。当然,你可以找到一种方法来实现这一点,而无需使用堆分配的字符串并直接在字符上操作。

一个显而易见的改进是调用AnsiUpperCase一次,传递整个字符串,并迭代返回的大写字符串。同样适用于AnsiLowerCase。或者您可以使用CharUpperBuffCharLowerBuff来避免堆分配。

当然还有整个Unicode问题。您使用的是Unicode Delphi,但仅限于ANSI。你真的想这么做吗?如果你想支持Unicode,那么你恐怕不得不停止使用Delphi集。您需要一种可以支持宽字符集的数据类型。您可能还需要考虑如何处理多字节UTF-16字符。

答案 1 :(得分:2)

  uses
      ..., AnsiStrings;

  type
    TSetOfChar = Set of AnsiChar;

  var
    CharacterSet: TSetOfChar;
    s: AnsiString;

    for j := 1 to Length(s) do
    begin
      Include(CharacterSet, s[j])
      if not CaseSensitive then
      begin
        Include(CharacterSet, AnsiStrings.AnsiUpperCase(s[j])[1]);
        Include(CharacterSet, AnsiStrings.AnsiLowerCase(s[j])[1]);
      end
    end;

可替换地:

  uses
      ..., AnsiStrings;

  type
    TSetOfChar = Set of AnsiChar;

  var
    CharacterSet: TSetOfChar;
    s, s2: AnsiString;

    if CaseSensitive then
    begin
      for j := 1 to Length(s) do
        Include(CharacterSet, s[j]);
    end else 
    begin
      s2 := AnsiStrings.AnsiUpperCase(s);
      for j := 1 to Length(s2) do
        Include(CharacterSet, s2[j]);
      s2 := AnsiStrings.AnsiLowerCase(s);
      for j := 1 to Length(s2) do
        Include(CharacterSet, s2[j]);
      end
    end;