Delphi case statements – using strings

Reading time: 4 – 6 minutes

  Years ago while working in happy Dos land, programming little game demos there, I hit a wall with my programming, and was forced to switch to Win32 programming if I wanted anyone to see my stuff.  The transition had one bump in the road (Known as FreePascal), but then I started using Delphi.  Took a while to get used to the whole WYSISYG, visual editor stuff, but after spending years of having to tweak menus and buttons at a per-pixel level, then having to compile and run the program just to see the changes, I can’t say I was upset.

  There was one change though that I still can’t figure out, it’s with the case statement.  C\C++ users know it as their switch staement (That uses case statement in each line).  In Pascal, this is fine:

  case  Temp of
  'bob' : begin end;
  'Tom' : begin end;
  end;

  Try that shit in Delphi, you get this error on the line “case Temp of”:

Ordinal type required

  So no more using strings inside of case statements.  Now some people may think “But I’ve seen them before!”.  No.  What you may have seen is something like this:

 case  Color of
    clRed : begin end;
    clBlue : begin end;
  end;

  clRed and clBlue are predefined.  One way around this that’s very sloppy is make a function called StrToOrd, like this:

function StrToOrd (AString : String) : int64;
var
  Loop : Integer;
begin
  Result := '';
  for loop := 1 to length (AString) do Result := strtoint(inttostr(Result)+inttostr(ord(AString[Loop])));
end;

  The returned value inside Result will be an int64 value of all the letters, so you’re very limited in char length.  And while it works, you can not do this:

case  StrToOrd(Edit1.Text) of
    StrToOrd('Bob') : Caption := 'You picked bob!';
    StrToOrd('Tom') : Caption := 'You picked tom!';
    else Caption := 'That''s not a choice!';
  end;

  This is because the items inside the case have to be static.  So in order to use this function, you have to do this:

case  StrToOrd(Edit1.Text) of
    36611198 : Caption := 'You picked bob!';
    384111109 : Caption := 'You picked tom!';
    else Caption := 'That''s not a choice!';
  end;

  At this point, you may as well use nested IFs unless there’s performance issues that require the case statement.

  There’s another way to go about using strings in case statements, the way most Delphi guys do it.  The command AnsiIndexText (Inside strutils) will return what item from an index of strings your text matches.  Confused?  Here’s how it works:

  case AnsiIndexText(Edit1.text,['Bob','Tom']) of
    0 : Caption := 'You picked bob!';
    1 : Caption := 'You picked tom!';
    else begin
      Caption := 'That''s not a choice!';
    end;
  end;

  Crude, but it works.  We can spice things up a bit by using a string list.  Now the strings inside a string list can not be passed to AnsiIndexText as-is, they’re data structures, so one way to do it:

  TStringArray = Record
    MyArray : Array of String;
  end;
  TMyStringList = class(TStringList)
    Private
      function GetArray : TStringArray;
    Public
      Property StringArray : TStringArray read GetArray;
  end;
var
  MyStrings : TMyStringList;
function TMyStringList.GetArray : TStringArray;
Var
  Loop : Integer;
Begin
  SetLength(Result.MyArray,Self.Count+1);
  For Loop := 0 to Self.Count-1 do Result.MyArray[Loop] := Self.Strings[Loop];
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  Temp : String;
  Loop : Integer;
begin
  case AnsiIndexText(Edit1.text,MyStrings.StringArray.MyArray) of
    0 : Caption := 'You picked bob!';
    1 : Caption := 'You picked tom!';
    else begin
      Caption := 'That''s not a choice!';
    end;
  end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  MyStrings := TMyStringList.Create;
  MyStrings.Add('Bob');
  MyStrings.Add('Tom');
end;

  This is still a big pain, but better than nothing. 

  The way I’m using this case statement in my last program is via a static array, I also have variables declared for each item:

Const
  PanelNames : Array [0..11] of String = ('PanelAgeUp' , 'PanelAgeDown','PanelMoveUp','PanelMoveDown','PanelACUp','PanelACDown','PanelSaveUp','PanelSaveDown','PanelLevelUp','PanelLevelDown','PanelStatUp','PanelStatDown');
  iPanelAgeUp = 0;
  iPanelAgeDown = 1;
  iPanelMoveUp = 2;
  iPanelMoveDown = 3;
  iPanelACUp = 4;
  iPanelACDown = 5;
  iPanelSaveUp = 6;
  iPanelSaveDown = 7;
  iPanelLevelUp = 8;
  iPanelLevelDown = 9;
  iPanelStatUp = 10;
  iPanelStatDown = 11;
Procedure TForm1.FindRepeat (Sender : TObject);
var
  MyPanel : TPanel;
Begin
  MyPanel := Sender as TPanel;
  Case AnsiIndexText(MyPanel.Name,PanelNames) of
    iPanelAgeUp : RepeatTimer.OnTimer := PanelAgeUpClick;
    iPanelAgeDown : RepeatTimer.OnTimer := PanelAgeDownClick;
    iPanelMoveUp : RepeatTimer.OnTimer := PanelMoveUpClick;
    iPanelMoveDown : RepeatTimer.OnTimer := PanelMoveDownClick;
    iPanelACUp : RepeatTimer.OnTimer := PanelACUpClick;
    iPanelACDown : RepeatTimer.OnTimer := PanelACDownClick;
    iPanelSaveUp : Begin RepeatTimer.OnTimer := PanelSaveClick; Modify := 1; end;
    iPanelSaveDown : Begin RepeatTimer.OnTimer := PanelSaveClick; Modify := -1; end;
    iPanelLevelUp : Begin RepeatTimer.OnTimer := PanelLevelClick; Modify := 1; end;
    iPanelLevelDown : Begin RepeatTimer.OnTimer := PanelLevelClick; Modify := -1; end;
    iPanelStatUp : Begin RepeatTimer.OnTimer := PanelStatClick; Modify := 1; end;
    iPanelStatDown : Begin RepeatTimer.OnTimer := PanelStatClick; Modify := -1; end;
  end;
End;

  The code above is so I can reuse one procedure for EVERY button since the program has about 45 buttons right now, it was getting pretty full of the same procedure over and over again.  Simple trick to overcome a pretty silly restriction in my book.

This entry was posted in Computers and networking, Delphi, Programming. Bookmark the permalink.

One Response to Delphi case statements – using strings

  1. LogiCoder says:

    Result := 0; no Result := ” -> Types incompatibles : ‘Int64′ et ‘string’

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>