Home > Net >  Delphi TSysCharSet , iterate through set of char
Delphi TSysCharSet , iterate through set of char

Time:06-26

I need to verify if a certain position in a string is part of a given valid charset. My code does not compile, how to iterate through set of char?

function Valid_Char_at_Index(const CheckStr: string; CheckPos : Integer ; ValidNextChars: TSysCharSet)
  : boolean;
var
  mychar : Char;
begin
  Result := false;
  for  each mychar in ValidNextChars do
      if (CheckStr(Length(CheckStr)) =mychar ) then
        Result:= True;

end;

CodePudding user response:

You don't need to iterate. Use CharInSet().

function Valid_Char_at_Index(const CheckStr: string; CheckPos : Integer ; ValidNextChars: TSysCharSet)
  : boolean;
begin
  Result := CharInSet(CheckStr[CheckPos],ValidNextChars);
end;

CodePudding user response:

First, it is not clear why you would expect for each to work at all, since Delphi doesn't have for each loops, as stated in the documentation. The documentation or a simple WWW search reveals that the corresponding Delphi concept is the for in loop.

Second, I don't understand at all what you mean by CheckStr(Length(CheckStr)) = mychar. Surely the predicate needs to contain the character index? And this is a syntax error, since CheckStr isn't a function or type. In fact, you simply want to check if the CheckPosth character of CheckStr is mychar.

Putting all this together, we end up with

function CheckCharAt(const AText: string; APos: Integer; ValidChars: TSysCharSet): Boolean;
var
  ValidChar: Char;
begin
  for ValidChar in ValidChars do
    if AText[APos] = ValidChar then
      Exit(True);
  Result := False;
end;

But please note that this only works for ASCII (and 8-bit character sets), so basically non-typographic English only, because of the TSysCharSet being a set of AnsiChar -- and a set of WideChar being an impossible type (since SizeOf(WideChar) = 2 > 1).

A simple way to fix this is to use an array of characters instead:

function CheckCharAt(const AText: string; APos: Integer; const ValidChars: array of Char): Boolean;
begin
  for var ValidChar in ValidChars do
    if AText[APos] = ValidChar then
      Exit(True);
  Result := False;
end;

But in modern Delphi versions, you don't need to write your own function at all, since you can simply use the TCharHelper.IsInArray method:

'test'[2].IsInArray(['a', 'e'])

Bonus info: If you only work with AnsiStrings (or ASCII-only strings), you should of course use the in set operator:

function CheckCharAt(const AText: AnsiString; APos: Integer; const ValidChars: TSysCharSet): Boolean;
begin
  Result := AText[APos] in ValidChars;
end;

But, as I stated above, a set of WideChar is not possible, so you have to abandon the entire set concept if you need more than 8-bit characters.

  • Related