I try to convert some code from D2007 to XE5 and got
E2010 Incompatible types: \'AnsiChar\' and \'Char\'
from this code
TSetOfChar = Set of Cha
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;
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.
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.
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:
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.
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.