StrToVar ? :)

Is there any way to make this kind of Procedure?

like

...
a : integer = 0;
b : integer = 0;
c : integer = 0;
d : integer = 0;
e : integer = 0;
...

Procedure StrToVar (variable : String ; value : integer);
begin
  ?? // well i need something different then "if variable = 'a' then" :)  
      // I want something that i can use with any variables ( int type )
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  StrToVar(edit1.text,strtoint(edit2.text)); // where edit1.text is 'a' and edit2.text is '5'
end;

Is there any way to make it work ? btw if its to much complicated i can incresse the points :)


thx in Advance
LVL 7
furmigaAsked:
Who is Participating?
 
Russell LibbyConnect With a Mentor Software Engineer, Advisory Commented:
Or in object form...


uses
  Windows, SysUtils, Classes;

type
  TIntArray      =  class(TObject)
  private
     FVariables: TStringList;
     FVarDelim:  Char;
     FValDelim:  Char;
  protected
     procedure   SetValue(Index: String; Value: Integer);
     procedure   SetText(Value: String);
     function    GetVariable(Index: Integer): String;
     function    GetText: String;
     function    GetValue(Index: String): Integer;
     function    GetCount: Integer;
  public
     constructor Create(VarDelim, ValDelim: Char);
     destructor  Destroy; override;
     property    Variables[Index: Integer]: String read GetVariable;
     property    Values[Index: String]: Integer read GetValue write SetValue;
     property    VarDelimiter: Char read FVarDelim write FVarDelim;
     property    ValDelimiter: Char read FValDelim write FValDelim;
     property    Text: String read GetText write SetText;
     property    Count: Integer read GetCount;
  end;

implementation

procedure TIntArray.SetText(Value: String);
var  lpszTemp:   PChar;
     lpszCur:    PChar;
     lpszVar:    PChar;
     lpszVal:    PChar;
begin

  // Allocate memory for parsing
  lpszTemp:=AllocMem(Succ(Length(Value)));
  try
     // Set current string pointer
     lpszCur:=lpszTemp;
     // Copy passed in string
     StrPCopy(lpszCur, Trim(Value));
     // Iterate while we have string
     while (lpszCur^ > #0) do
     begin
        // Skip past empty variables, or starting marker
        while (lpszCur^ = FVarDelim) and (lpszCur^ > #0) do Inc(lpszCur);
        // Break if at string end
        if (lpszCur^ = #0) then break;
        // Get the variable name
        lpszVar:=lpszCur;
        // Skip to the value delimiter
        while (lpszCur^ <> FValDelim) and (lpszCur^ > #0) do Inc(lpszCur);
        if (lpszCur^ = #0) then break;
        // Null out and set the value start
        lpszCur^:=#0;
        Inc(lpszCur);
        lpszVal:=lpszCur;
        // Find the end of the value
        while (lpszCur^ <> FVarDelim) and (lpszCur^ > #0) do Inc(lpszCur);
        // Terminate if we are sitting on a variable delimiter
        if (lpszCur^ = FVarDelim) then
        begin
           lpszCur^:=#0;
           Inc(lpszCur);
        end;
        // Add the variable setting
        SetValue(lpszVar, StrToIntDef(lpszVal, 0));
     end;
  finally
     // Free allocated memory
     FreeMem(lpszTemp);
  end;

end;

function TIntArray.GetText: String;
var  dwIndex:    Integer;
begin

  // Build result string
  result:=FVarDelim;
  for dwIndex:=0 to Pred(FVariables.Count) do
  begin
     result:=result+FVariables[dwIndex]+FValDelim+IntToStr(Integer(FVariables.Objects[dwIndex]));
  end;

end;

function TIntArray.GetVariable(Index: Integer): String;
begin

  // Return the variable name
  result:=FVariables[Index];

end;

procedure TIntArray.SetValue(Index: String; Value: Integer);
var  dwIndex:    Integer;
begin

  // Search for variable
  if FVariables.Find(Index, dwIndex) then
     // Update
     FVariables.Objects[dwIndex]:=TObject(Value)
  else
     // Add new
     FVariables.AddObject(Index, TObject(Value));

end;

function TIntArray.GetValue(Index: String): Integer;
var  dwIndex:    Integer;
begin

  // Search for variable
  if FVariables.Find(Index, dwIndex) then
     result:=Integer(FVariables.Objects[dwIndex])
  else
     result:=0;

end;

function TIntArray.GetCount: Integer;
begin

  // Return count of variables
  result:=FVariables.Count;

end;

constructor TIntArray.Create(VarDelim, ValDelim: Char);
begin

  // Perform inherited
  inherited Create;

  // Set starting values
  FVariables:=TStringList.Create;
  FVarDelim:=VarDelim;
  FValDelim:=ValDelim;

end;

destructor TIntArray.Destroy;
begin

  // Cleanup
  FVariables.Free;

  // Perform inherited
  inherited Destroy;

end;

-------------------
usage

var  dwIndex:    Integer;
begin

  with TIntArray.Create('@', '=') do
  begin
     Text:='@Armor_lvl=3@life=45@gold=4555';
     ShowMessage(Text);
     for dwIndex:=0 to Pred(Count) do
        ShowMessage(Format('%s = %d', [Variables[dwIndex], Values[Variables[dwIndex]]]));
  end;

end;


---

Russell


0
 
shaneholmesCommented:
to limit on using many if thens, you could use a case statement...I know, I know, case statements are for ordinal types,
well, maybe this can help!

http://groups.google.com/groups?q=Delphi++%2B+Strings+%2B+Case&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=3949265d%240%2462934%2445beb828%40newscene.com&rnum=3


The only other way I can thing of is to create a class wrapper  which holds the String and value representation.

type

 TWrap
  Name: String;
  Value: Integer;
 end;

var

 Wrap: TWrap;

Shane
0
 
shaneholmesCommented:
Or you can create a TStringList, populate it with the values you are looking
for pass it to this function


Function GetValue(Name: String; List: TStrings): Integer
begin
 case List.IndexOf(Name) of
 0: result:= 100;
 1: result:= 200;
 etc. etc.
 end;
end.

Shane
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
mokuleCommented:
You can try like this

var
  s: TStrings;
  ind: integer;


begin
  s:= TStringList.Create;
  s.AddObject('one',TObject(12));
  s.AddObject('two',TObject(257));
  s.AddObject('three',TObject(311));
................


usage


var
  ind: integer;
begin
  ind :=  s.IndexOf(Edit1.Text);
  if ind >= 0 then
    Edit2.Text := IntToStr(integer(s.Objects[ind]))
  else
    Edit2.Text := 'NotFound';
0
 
mokuleCommented:
Another nice solution is
TRegIniFile
and
function ReadInteger(const Section, Ident: String; Default: Longint): Longint;

0
 
Russell LibbySoftware Engineer, Advisory Commented:
Another possible...

var
  // IntArray
  IntArray:      Array ['A'..'Z'] of Integer = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);

implementation
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var  c:       Char;
begin

  c:='A';
  IntArray[UpCase(c)]:=5;
  ShowMessage(IntToStr(IntArray['A']));

end;

----------

Regards,
Russell
0
 
shaneholmesCommented:
Wow, the possibilities just keep adding up!

<SMILE>

Shane
0
 
esoftbgCommented:
it could be
1. way:
var
  AI:  array['a'..'z'] of Integer;

1. way:
type
  TNVRec = record
    Name:  string;
    Value:  Integer;
  end;
//  TNVArr = array of TNVRec;
//  TNVArr = array[1..25] of TNVRec;
  TNVArr = array [0..65535] of TNVRec;

var
  NVArr:  TNVArr;

emil
0
 
furmigaAuthor Commented:
okie.. lemmi try explain again ( after i read the topic i was like confused heh )

var
  Form1: TForm1;
  armor_lvl : integer = 0;
  life : integer = 0;
  gold : integer = 0;        

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);
var
variables, VarPart , VarValue: String;
I , total : integer;
begin

     //1 - I have a Indy client TCP that sends the command "GetChanged" to the server.
     WriteLn('GetChanged');

     //2 - The server writes me all variables changed since the last command and I save it into a var.
     variables := ReadLn;

     //3 - now supose this time the variables value is '@Armor_lvl=3@life=45@gold=4555'

     //4 - now i count how many '@' are in variables and save it in total

     for I := 0 to total do
     begin
          // using the var VarPart i store the ' I ' part of the string like: ( using a function..... )
          VarPart = 'Armor_lvl';
          // using the var VarValue i store the ' I ' part of the string like: ( using a function..... )
          VarValue = '3';
          // now this is what i want. I want to modify the REAL variables armor_lvl, life and gold
          using the VarPart / VarValue variables without using the if then statement.
          // something like
          StrToVar(VarPart) := StrToInt(VarValue)
     end;
end;

I guess now u guys can undertand me better :)

 rllibby I liked your suggestion but im still waiting for a StrToVar answer since if i use an array to save my vars all the program will have to be build in a array mode and every time i need to call a var i will have to call the array and i dont know if this can be a good way.


Well I ll add more 100 points. This can help me a bit :)
0
 
shaneholmesCommented:

Send the entire string to a TStringList as was suggested above, parsing out the name & values and using the
TSTringList AddObject method to add it to the list

OTTOMH something like

procedure  BuildList(List: TStrings; Data: String);
var
 I: Integer;
 Name: String;
 Value: Integer;
 tmpStr: String;
begin

 for I:= 2 to length(Data) do
 begin
  if (Data[I] <> '@') then
   Name:= Name + Data[I]
  else
   List.AddObject(Name,TObject(0));

 for I:= 0 to List.Count - 1 do
 begin
 List.Objects[I]:= StrToInt(Copy(List[I],pos('=',List[I]),Length(List[I])));
 tmpStr:= List[I];
 Delete(tmpStr, pos('=',List[I]) + 1,Length(List[I]));
 List[I]:= tmpStr;
 end;  

end;

Shane
0
 
shaneholmesCommented:
The indexes may be off give or take a number, - it was OTTOMH

And, Im sure someone can make it more robust - <smile>
0
 
mokuleCommented:
As in my solution.
It should work
 
var
  ind: integer;
begin
  ind :=  s.IndexOf(VarPart);
  if ind >= 0 then
    s.Delete(ind);

  s.AddObject(VarPart,TObject(VarValue));
0
 
shaneholmesCommented:
OOps, sorry, a typo


 for I:= 2 to length(Data) do

< begin> "remove"
 
 if (Data[I] <> '@') then
   Name:= Name + Data[I]
  else
   List.AddObject(Name,TObject(0));

shane
0
 
Russell LibbySoftware Engineer, Advisory Commented:
My bad on the constructor...

constructor TIntArray.Create(VarDelim, ValDelim: Char);
begin

  // Perform inherited
  inherited Create;

  // Set starting values
  FVariables:=TStringList.Create;
  FVariables.Sorted:=True;                // <----- Add the following 2 lines
  FVariables.Duplicates:=dupIgnore;   //  
  FVarDelim:=VarDelim;
  FValDelim:=ValDelim;

end;

----------

Russell
0
 
furmigaAuthor Commented:
Russell u kinda crazy :) ty man it worked fine.
0
 
shaneholmesCommented:
All of that just to parse that line of text -- OK, what ever floats your boat - :)

Shane
0
 
mokuleCommented:
A gift for furmiga
// parsing a line

uses RegExpr;


procedure TForm1.Parse(AText: string);
var
  xxx: TRegExpr;
begin
  ListBox1.Clear;
  xxx := TRegExpr.Create;
  xxx.Expression := '(@)(\w+)(=)(\d+)';

  if xxx.Exec(AText) then
  repeat
    ListBox1.Items.Add(xxx.Match[2]+','+xxx.Match[4])
  until not xxx.ExecNext;
  xxx.Free
end;

Marek
;-)
0
 
Russell LibbySoftware Engineer, Advisory Commented:

I was trying to demonstrate the purpose of object encapsulation. I mean, it takes 20 lines of code just to SET the information, and it still means maintaining the list in the application code. If the big picture is taken into consideration, then the app is going to need to read/write values itself (using the var name).( and these variables may/may not already exist). The app may also need to build a string of the variables to send the changed info back to the server. So now instead of creating a string list to maintain this, you create a lightweight object that handles all aspects of the data.

So considering the full scope of use, 160 lines of code is minimal, plus its encapsulated.

Russell
0
 
shaneholmesCommented:
No, No, dont get me wrong Russell, I know what you were doing....

I also know what he wanted, this is his second post i believe. I think he also posted the question regarding sending the commands back & fourth via CLient?Server communications.

If he would have hued my suggestions (assuming it was him) from his first post, then he would have not needed all this..

Shane
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.