Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Wanet Telecoms Ltd on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Trouble with Variant Open Array 1

Status
Not open for further replies.

Griffyn

Programmer
Jul 11, 2002
1,077
AU
Hi all,

I'm trying to use the Format function. For it's second parameter it takes a variant open array (array of const).

I have the array already set up and want to pass it to the Format function, but I keep running into a wall with invalid types and the like.

Some code:

Code:
var
  StrArray : array[1..10] of String;
begin
  { Load StrArray with values here }
  Format('%s, %d', StrArray);
end;

I've mucked around setting up a variant array but still can't get it to work.

Help anyone?
 
oops. just so nobody jumps on me, the code should be:

Code:
var
  StrArray : array[1..10] of String;
begin
  { Load StrArray with values here }
  Format('%s, %s', StrArray);
end;
 
Not entirly sure what you are trying to do but in you example, your array is a string array but you are expecting a decimal (integer) value as the second parameter.
You can load variables
d := 2;
s := 'world';
edit1.text := format('hello %d %s',[d, s]);
But I am not not sure if you can pre-initalise this sort of structure.



Steve
Be excellent to each other and Party on!
 
I appreciate your thoughts Steve. As you can see from my post above, I didn't mean to indicate I was trying to pass an integer.

Pre-initialisation is exactly what I'm trying to do here.
 
From what I've read you can only pass values as a variant open array parameter if you pass it as an "open array constructor" i.e. a sequence of expressions separated by commas and enclosed by square brackets (e.g. ['a', 'b', 'c']).

The only way I've been able to get your code to work is by doing the following which is far from ideal:
Code:
var
  StrArray : array[1..10] of String;
begin
  { Load StrArray with values here }
  Format('%s, %s', [StrArray[1], StrArray[2]]);
end;
It seems we are unable to exploit the potential power of variant open array paramaters because we cannot pass typed arrays.

Clive [infinity]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer."
Paul Ehrlich
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
Sorry as you say I did get in a bit too quickly.
There is alway a way to do things as Clive shows, but would that gain you anything? Sometimes it's easier to try another tack altogether.

e.g. formating your strings before output using type conversion funtions Inttostr(), etc.

Its the 'const' statments here that restrict the usage, its meant to be used as shown in the help file

function Format(const Format: string; const Args: array of const): string;







Steve
Be excellent to each other and Party on!
 
Thanks for your thoughts guys. I've had a little bit of success with the following code:

Code:
var
  t : array of TVarRec;
  x : array[1..2] of String;
  c : Integer;
begin
  x[1] := 'blah';  // testing - in my prog this happens
  x[2] := 'x';     // elsewhere
  SetLength(tx, Length(x));
  for c := 1 to Length(x) do
    tx[c-1].VString := PShortString(Pointer(x[c]));
  Format('%s, %s', tx);
end;

It runs, but the Format function throws an EConvertError exception. I think I've screwed up with the pointers in the code. Certainly the watch window shows tx[0] equals a whole stack of garbage.

Just so there's no illusions, my actual program has 20 parameters instead of 2. :)

Can anyone help me over the final hurdle?
 
gah. sorry, replace the 'tx' variable in that code with 't'. Must learn not to modify code after compilation.
 
I think the convert error is happening because the Format function is expecting the first argument to be a string and it is a TVarRec. I expect it doesn't know how to process the TVarRec in order to get the VString back out.

I guess what you could do is write your own Format function, or choose a completely different method as Steve suggested.

What exactly are you trying to do ultimately? Maybe we could make a more appropriate suggestion if we knew.

If you are simply trying to create a comma-delimited set of strings from an array of string then use TStringList and its DelimitedText property:
Code:
var
  StrArray: Array[1..20] of String;
Code:
var
  StrList: TStringList;
  i: Integer;
begin
  StrList := TStringList.Create;
  try
    LoadArrayValues;
    for i := Low(StrArray) to High(StrArray) do
      StrList.Add(StrArray[i]);
    Edit1.Text := StrList.DelimitedText;
  finally
    StrList.Free;
  end;
end;



Clive [infinity]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer."
Paul Ehrlich
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
From what I've gleaned from the help files, array of const and array of TVarRec are the same. You can see this if you Control+Click the word 'Format' in the code (in the IDE) and then rest your mouse on the FmtStr procedure reference to show the syntax it's expecting. It's expecting an array of TVarRec, and it's passing an array of const. This is how I got on to this tack.

I've kept my example code simple to avoid confusion. But seeing as we should be maybe looking for a way around the problem, I'll detail it.

I'm at the point in my program (a role playing game) where I'm trying to write some descriptive text to a Log file. The descriptive text is being constructed using the Format function and an array of specifics. eg. Taken from the database might be a single field:

"AdjustSkill,Long Sword,Maximum,10"

Which to the program will mean that the character's maximum long sword skill is being changed by 10. The descriptive template for the AdjustSkill event looks like this:

"The character's %2:s %1:s skill has been adjusted by %3:s"

Prior to the text going through the Format command, the 4 (can be any number though; it depends on the event type) parameters are separated into an array of String so they can be passed to the AdjustSkill method.

It would be nice to be able to pass my array of String into the Format function without further ado, rather than setting a limit on the number of parameters any event can have, and then hard-coding that into the call to Format.

I could write my own Format function - it's certainly something I could do, but I'd like to explore this avenue to the end first.
 
I have a program where I do just the same as you do.

this code is tested and works :

Code:
procedure test(strlist : TStringList);

var output : string;
    Args   : array of TVarrec;
    i      : integer;


begin
 SetLength(Args,StrList.Count);
 for i:=0 to StrList.Count-1 do
  begin
   Args[i].VType:=VtPChar;
   Args[i].VPChar:=PChar(StrList[i]);
  end;
 case StrList.Count of
  2 : output:=format('%s %s', Args);
  3 : output:=format('%s %s %s',Args);
 end;
 showmessage(output);
end;


procedure TForm1.Button1Click(Sender: TObject);

var StrList : TStringList;

begin
 StrList:=TStringList.Create;
 StrList.Add('one');
 StrList.Add('two');
 test(StrList);
 FreeAndNil(StrList);
end;

procedure TForm1.Button2Click(Sender: TObject);
var StrList : TStringList;

begin
 StrList:=TStringList.Create;
 StrList.Add('one');
 StrList.Add('two');
 StrList.Add('three');
 test(StrList);
 FreeAndNil(StrList);
end;

--------------------------------------
What You See Is What You Get
 
Awesome. I'll trust you that it works whosrdaddy. Where were you two days ago? :) A star for you, and many thanks to everyone you tried to help out.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top