Recent

Author Topic: Passing an open typed array as a parameter  (Read 2560 times)

Bazzao

  • Full Member
  • ***
  • Posts: 178
  • Pies are squared.
Passing an open typed array as a parameter
« on: February 20, 2019, 10:03:00 am »
I'm trying to teach myself how to pass, as a parameter, a open-ended typed array.

I get the message:
Error: Incompatible type for arg no. 3: Got "{Array Of Const/Constant Open} Array of Constant String", expected "TStrIntRecArr"

Code: Pascal  [Select][+][-]
  1. type
  2.   TStrIntRec=record
  3.     rStr:string;
  4.     rInt:integer;
  5.   end;
  6.   TStrIntRecArr=array of TStrIntRec;
  7.  
  8. procedure ShowDebug(pMode:integer; pTit:string; const pArr:TStrIntRecArr);
  9. var I,K,L:integer; S,T:string;
  10. begin
  11.   K:=0;
  12.   for I:=Low(pArr) to High(pArr) do
  13.     begin
  14.       S:=pArr[I].rStr;
  15.       L:=length(S);
  16.       if L>K then K:=L;
  17.     end;
  18.   T:=pTit+':||';
  19.   for I:=Low(pArr) to High(pArr) do
  20.     if pMode=3 then
  21.       T:=T+IntToStr(pArr[I].rInt)+'='+pArr[I].rStr+'||'
  22.     else
  23.     if pMode=2 then
  24.       begin
  25.         S:=copy(pArr[I].rStr+'        ',1,K);
  26.         T:=T+S+'='+IntToStr(pArr[I].rInt)+'||';
  27.       end
  28.     else
  29.       T:=T+pArr[I].rStr+'||';
  30.   T:=StringReplace(T,'||',#13#10,[rfReplaceAll,rfIgnoreCase]);
  31.   ShowMessage(T);
  32. end;
  33.  
  34. procedure TForm1.Button1Click(Sender: TObject);
  35. begin
  36.   ShowDebug(1,'Mode 1',['One',1,'Two',2,'Three',3]);
  37.   ShowDebug(2,'Mode 2',['One',1,'Two',2,'Three',3]);
  38.   ShowDebug(3,'Mode 3',['One',1,'Two',2,'Three',3]);
  39. end;
  40.  

TIA,

Bazza
Bazza

Lazarus 2.0.10; FPC 3.2.0; SVN Revision 63526; x86_64-win64-win32/win64
Windows 10.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Passing an open typed array as a parameter
« Reply #1 on: February 20, 2019, 11:39:20 am »
You did not pass on array of TStrIntRec! Instead you pass a const array of const (...; const Args : Array of const; ...)

What is your intention? Passing like you did or passing records?

You should have a look at SysUtils.Format if your intention is to pass all values as you did.

laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Bazzao

  • Full Member
  • ***
  • Posts: 178
  • Pies are squared.
Re: Passing an open typed array as a parameter
« Reply #2 on: February 20, 2019, 12:30:44 pm »
Hi Pascal,

Thanks for replying.

The object is to pass constants & variables, not all constants. I just wanted to get the structure correct. A previous working version of this I had the strings & integers in two separate arrays, but thought I could create a record and pass it that way.

I tried passing an array of TStrIntRec, but the same error came up.

Bazza




Bazza

Lazarus 2.0.10; FPC 3.2.0; SVN Revision 63526; x86_64-win64-win32/win64
Windows 10.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Passing an open typed array as a parameter
« Reply #3 on: February 20, 2019, 12:47:24 pm »
The problem is that you did not do what you defined! You pass discrete values and not records.
You can do it that way, no problem, but then you have to define it this way:
Code: Pascal  [Select][+][-]
  1. procedure ShowDebug(pMode:integer; pTit:string; const pArr : Array of const);

Then you have to take care that you get pairs of strings and integers.
« Last Edit: February 20, 2019, 02:22:21 pm by Pascal »
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Passing an open typed array as a parameter
« Reply #4 on: February 20, 2019, 02:40:50 pm »
When using the array of const syntax you are restricted to the (simple) types supported by TVarRec, which excludes any type of record.

Because of the many string types Pascal supports, it is somewhat more involved than you might think to parse an array of const which includes strings.
I think what you are looking for is something like the following
Code: Pascal  [Select][+][-]
  1.  procedure ShowDebug(aMode: Integer; aTitle: String; anArr: array of const);
  2.  
  3. implementation
  4.  
  5. uses strutils;
  6.  
  7. procedure ShowDebug(aMode: Integer; aTitle: String; anArr: array of const);
  8.  
  9.   function GetNextString(anIdx: Integer; out OK: Boolean): String;
  10.   begin
  11.     OK := False;
  12.     if anIdx >= High(anArr) then
  13.       Exit('');
  14.     case anArr[anIdx].VType of
  15.       vtAnsiString: Result := AnsiString(anArr[anIdx].VAnsiString);
  16.       vtChar:       Result := anArr[anIdx].VChar;
  17.       vtPChar:      Result := anArr[anIdx].VPChar;
  18.       vtPWideChar:  Result := anArr[anIdx].VPWideChar;
  19.       vtString:     Result := anArr[anIdx].VString^;
  20.       vtWideChar:   Result := AnsiString(anArr[anIdx].VWideChar);
  21.       vtWidestring: Result := AnsiString(WideString(anArr[anIdx].VWideString));
  22.       else Exit('');
  23.     end;
  24.     OK := True;
  25.   end;
  26.  
  27. var
  28.   i: Integer;
  29.   maxLen: Integer = 0;
  30.   isOK: Boolean;
  31.   msg, s, st: String;
  32.   sArr: array of String;
  33. begin
  34.   msg := aTitle + #10;
  35.   i := Low(anArr);
  36.   SetLength(sArr, 0);
  37.   while i < High(anArr) do
  38.     begin
  39.       s := GetNextString(i, isOK);
  40.       if not isOK then
  41.         Inc(i)
  42.       else
  43.         begin
  44.           if Length(s) > maxLen then
  45.             maxLen := Length(s);
  46.           Inc(i);
  47.           if anArr[i].VType = vtInteger then begin
  48.             case aMode of
  49.               1: msg := msg + s + #10;
  50.               2: begin
  51.                    SetLength(sArr, Length(sArr)+1);
  52.                    sArr[High(sArr)] := s;
  53.                  end;
  54.               3: msg := msg + IntToStr(anArr[i].VInteger) + ' = ' + s + #10;
  55.               else msg := '';
  56.             end;
  57.             Inc(i);
  58.           end;
  59.         end;
  60.     end;
  61.   case isOK of
  62.     True: begin
  63.             if (aMode = 2) then
  64.               begin
  65.                 s := '';
  66.                 Inc(maxLen);
  67.                 for st in sArr do
  68.                   s := s + PadLeft(st, maxLen) + #10;
  69.                 msg := msg + s;
  70.               end;
  71.             case (msg = '') of
  72.               True:  ShowMessage('Error in parsing parameters');
  73.               False: ShowMessage(msg);
  74.             end;
  75.           end;
  76.     False: ShowMessage('Error in parsing parameters');
  77.   end;
  78. end;
  79.  
  80. procedure TForm1.Button1Click(Sender: TObject);
  81. begin
  82.   ShowDebug(1,'Mode 1',['One',1,'Two',2,'Three',3]);
  83.   ShowDebug(2,'Mode 2',['One',1,'Two',2,'Three',3]);
  84.   ShowDebug(3,'Mode 3',['One',1,'Two',2,'Three',3]);
  85.   ShowDebug(3,'Mode 3',[9,'nine']);
  86. end;
« Last Edit: February 21, 2019, 05:27:22 am by howardpc »

Bazzao

  • Full Member
  • ***
  • Posts: 178
  • Pies are squared.
Re: Passing an open typed array as a parameter
« Reply #5 on: February 25, 2019, 12:22:32 am »
Many thanks Pascal & Howardpc. Got it.

Sometimes Pascal (the language) wasn't made to be easy.

B
Bazza

Lazarus 2.0.10; FPC 3.2.0; SVN Revision 63526; x86_64-win64-win32/win64
Windows 10.

 

TinyPortal © 2005-2018