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.
s[1] in ['A'..'Z','a'..'z','0'..'9']
in recent Delphi versions. Since I don't care about anything outside of the Ansi-range, I doAnsiChar(s[1]) in [
etc. – Stijn SandersCharInSet()
, like the compiler warning says. – Remy Lebeau