How to specify multiple ranges for an if statement in Delphi?

Viewed 1620
    for counter := 1 to lengthofpassword do
  begin
    currentletter:=password[counter];
    currentascii:=Ord(currentletter);
    if (96<currentascii<123) OR (64<currentascii<91) OR (47<currentascii<58) then
    Writeln('valid')
    else
    asciicheck:=false;
  end;

I know this code is wrong but I did it to explain what I want to ask. How can you specify ranges for an if statement? Before, I messed around with lots of if statements and my code wasn't working the way I wanted it to. Basically, I am making a procedure which checks the user input for anything other than uppercase and lowercase alphabet and numbers. This question is different because I was looking for how this problem could be solved using a Case Of statement.

    for counter := 1 to lengthofpassword do
  begin
    currentletter:=password[counter];
    currentascii:=Ord(currentletter);
    if (currentascii<48) AND (currentascii>57) then
    asciipoints:=asciipoints+1;
    if (currentascii<65) AND (currentascii>90) then
    asciipoints:=asciipoints+1;
    if (currentascii<97) AND (currentascii>122) then
    asciipoints:=asciipoints+1;
    Writeln(asciipoints);
  end;

I also tried to do it like this but then realised this wouldn't work because if one statement was satisfied, the others wouldn't be and the points based system wouldn't work either.

3 Answers

Glad you found the answer yourself.

Another way to make sure the password only contains upper and lower case characters and numbers is what I tried to point to: define a set of characters that are valid and check if each character in your password is in these valid characters.

So with a set defined like this:

const 
  ValidChars = ['A'..'Z', 'a'..'z', '0'..'9'];

you can use statements like

if password[I] in ValidChars then

This statement will however generate a compiler warning in Unicode Delphi, as the type in a set is limited to 256 possible values, and their ordinalities must fall between 0 and 255. This isn't the case for WideChar with 65.536 values. So the set of char defined is in fact a set of AnsiChar. For this task this is acceptable, as every character that needs to be checked is ASCII, so using the function CharInSet will not generate a compiler warning and have a defined behavior - returning False - if the password contains Unicode characters.

This is the resulting code:

const 
  ValidChars = ['A'..'Z', 'a'..'z', '0'..'9'];
var
  I: Integer;
begin
  for I := 1 to passwordlength do
  begin
    if CharInSet(password[I], ValidChars) then  
      Writeln('valid')  // more likely to do nothing and invert the if statement
    else
    begin
      asciicheck := False;
      Break; // No need to look further, the check failed
    end;
  end;
end;

Multiple ranges is best expressed in a case statement:

begin
  for counter := 1 to lengthofpassword do
  begin
    case Ord(password[counter]) of
      48..57,
      65..90,
      97..122 :
        Writeln('valid')
      else
        asciicheck:=false;
    end;
  end;
end;

Now, this works for characters < #128. If you are working in a unicode application and don't want the restriction of characters being the english alphabet, it is possible to use TCharHelper.IsLetterOrDigit.

if password[counter].IsLetterOrDigit then ...

Thanks to a comment up above, I have found a solution. I ended up using a Case Of statement like this:

    for counter := 1 to lengthofpassword do
  begin
    currentletter:=password[counter];
    currentascii:=Ord(currentletter);
      case currentascii of
        97..122 : asciicheck:=true;
        65..90  : asciicheck:=true;
        48..57  : asciicheck:=true;
        else asciicheck:=false;
      end;
  end;

Thanks once again.

Related