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

时间:2021-08-10 16:14:05

I try to convert some code from D2007 to XE5 and got

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

E2010 Incompatible types: 'AnsiChar' and 'Char'

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

from this code

从这段代码

  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;

Any suggestion for solution ? I think it is enough to handle AnsiStrings.

对解决方案有什么建议吗?我认为这足够处理一个问题了。

2 个解决方案

#1


2  

The base type for a Delphi set can have at most 256 elements. Which means that your set is in fact really set of AnsiChar.

Delphi集合的基本类型最多可以有256个元素。这意味着你的集合实际上是一组AnsiChar。

And your code is failing because AnsiUpperCase(s[j]) is of type string which is UnicodeString. Hence AnsiUpperCase(s[j])[1] is of type char which is WideChar. Which is what the compiler is trying to tell you. Despite their names, AnsiUpperCase and AnsiLowerCase operate on, and return UnicodeString.

您的代码失败了,因为AnsiUpperCase(s[j])是字符串类型,它是UnicodeString。因此,AnsiUpperCase(s[j])[1]是char类型的字符。这就是编译器要告诉你的。尽管他们的名字,AnsiUpperCase和AnsiLowerCase操作,并返回UnicodeString。

If you really do still want to work with ANSI strings then you will need to use the AnsiUpperCase and AnsiLowerCase functions from the AnsiStrings unit. These versions operate on, and return AnsiString. Add that unit to your uses clause, and make sure you pass AnsiString values:

如果您仍然想要使用ANSI字符串,那么您需要使用ansistring单元的AnsiUpperCase和AnsiLowerCase函数。这些版本操作,并返回AnsiString。将该单元添加到您的use子句中,并确保传递了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;

Of course, it seems extremely inefficient to be creating strings containing single characters. Surely you can find a way to do this without using heap allocated strings and operating directly on characters.

当然,创建包含单个字符的字符串似乎非常低效。当然,您可以找到一种方法,无需使用堆分配的字符串并直接操作字符。

An obvious improvement would be to call AnsiUpperCase once, passing the entire string, and iterate over the upper case string returned. Likewise for AnsiLowerCase. Or you could use CharUpperBuff and CharLowerBuff to avoid heap allocations.

一个明显的改进是调用AnsiUpperCase一次,传递整个字符串,并遍历返回的上一个case字符串。同样AnsiLowerCase。或者您可以使用CharUpperBuff和CharLowerBuff来避免堆分配。

And of course there's the whole issue of Unicode. You are using a Unicode Delphi but being confined to ANSI. Do you really want to do that? If you want to support Unicode then you have to stop using Delphi sets, I am afraid. You'll need a data type that can support sets of wide characters. You would also perhaps need to consider what to do with multi-byte UTF-16 characters.

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

#2


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;

Alternatively:

另外:

  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;

#1


2  

The base type for a Delphi set can have at most 256 elements. Which means that your set is in fact really set of AnsiChar.

Delphi集合的基本类型最多可以有256个元素。这意味着你的集合实际上是一组AnsiChar。

And your code is failing because AnsiUpperCase(s[j]) is of type string which is UnicodeString. Hence AnsiUpperCase(s[j])[1] is of type char which is WideChar. Which is what the compiler is trying to tell you. Despite their names, AnsiUpperCase and AnsiLowerCase operate on, and return UnicodeString.

您的代码失败了,因为AnsiUpperCase(s[j])是字符串类型,它是UnicodeString。因此,AnsiUpperCase(s[j])[1]是char类型的字符。这就是编译器要告诉你的。尽管他们的名字,AnsiUpperCase和AnsiLowerCase操作,并返回UnicodeString。

If you really do still want to work with ANSI strings then you will need to use the AnsiUpperCase and AnsiLowerCase functions from the AnsiStrings unit. These versions operate on, and return AnsiString. Add that unit to your uses clause, and make sure you pass AnsiString values:

如果您仍然想要使用ANSI字符串,那么您需要使用ansistring单元的AnsiUpperCase和AnsiLowerCase函数。这些版本操作,并返回AnsiString。将该单元添加到您的use子句中,并确保传递了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;

Of course, it seems extremely inefficient to be creating strings containing single characters. Surely you can find a way to do this without using heap allocated strings and operating directly on characters.

当然,创建包含单个字符的字符串似乎非常低效。当然,您可以找到一种方法,无需使用堆分配的字符串并直接操作字符。

An obvious improvement would be to call AnsiUpperCase once, passing the entire string, and iterate over the upper case string returned. Likewise for AnsiLowerCase. Or you could use CharUpperBuff and CharLowerBuff to avoid heap allocations.

一个明显的改进是调用AnsiUpperCase一次,传递整个字符串,并遍历返回的上一个case字符串。同样AnsiLowerCase。或者您可以使用CharUpperBuff和CharLowerBuff来避免堆分配。

And of course there's the whole issue of Unicode. You are using a Unicode Delphi but being confined to ANSI. Do you really want to do that? If you want to support Unicode then you have to stop using Delphi sets, I am afraid. You'll need a data type that can support sets of wide characters. You would also perhaps need to consider what to do with multi-byte UTF-16 characters.

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

#2


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;

Alternatively:

另外:

  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;