Solved

Delphi Loading Data Into Two Dynamic Arras From a Single Procedure

Posted on 2010-08-24
42
394 Views
Last Modified: 2013-11-23
I have a called lest say, Procedure1, declaring the following two dtynamic arrays:
Var SourceArray, DestArray : array of String;

From Procedure1 I want to call Procedure2 or Function2 where I want to load data into SourceArray or DestArray, by passing the name of the Array to Procedure 2, hence controlling through the passing of the Array's name, into which Array Procedure 2 is to load the data.  How is this done?
0
Comment
Question by:HenryM2
  • 16
  • 8
  • 7
  • +5
42 Comments
 
LVL 9

Expert Comment

by:sas13
Comment Utility
type
  TMyArray = array of String;

var
  SourceArray, DestArray : TMyArray;

// using

proedure Procedure2(const Source: TMyArray; var Dest: TMyArray);
...
0
 
LVL 13

Assisted Solution

by:aflarin
aflarin earned 166 total points
Comment Utility
Something like this?

type
  TStringArray = array of string;

procedure Procedure2(SourceArray: TStringArray; var DestArray: TStringArray);
var
  i: Integer;
begin
  SetLength( DestArray, Length(SourceArray) );
  for i:= Low(SourceArray) to High(SourceArray) do
    DestArray[i]:= SourceArray[i];
end;

procedure TForm1.Procedure1(Sender: TObject);
var
  SourceArray, DestArray : TStringArray;
begin
  SetLength(SourceArray, 2);
  SourceArray[0]:= 'Hello ';
  SourceArray[1]:= 'World!';
  Procedure2( SourceArray, DestArray );
  ShowMessage( DestArray[0] + DestArray[1] );
end;
0
 
LVL 58

Expert Comment

by:cyberkiwi
Comment Utility
SourceArray and DestArray will need to be visible to Procedure2.
3 options:
Procedure2 will be an internal procedure to Procedure1
SourceArray/DestArray is passed directly to Procedure2
SourceArray, DestArray are declared globally.

Assuming Proc2 is external to Proc1, I would just pass the array by reference.
I don't understand why you would pass the name instead of the array directly?

procedure Proc1(Var SourceArray, DestArray : array of String);
begin
  // do something
  Proc2(SourceArray); // or DestArray
  // do something else
end;

Procedure Proc2(Var anArray: array of String);
begin
  // do something
end;
0
 
LVL 36

Accepted Solution

by:
Geert Gruwez earned 167 total points
Comment Utility
the code word you are looking for is "VAR"

- to pass data to a procedure which doesn't have to alter that variable:
type
  TMyArray = array of string;
procedure Test1(arr: TMyArray);
begin
  ShowMessage(Format('Array elements: %d', [High(arr)]));
end;

to pass data to a procedure which has to alter (or fill in the variable):
type
  TMyArray = array of string;
procedure Test2(var arr: TMyArray);
var I: Integer;
begin
  SetLength(arr, 10);
  for I := Low(arr) to High(arr) do
    arr[I] := IntToStr(I);
end;

you can also alter the number of parameters
type
  TMyArray = array of string;
procedure Test3(var arr1, arr2: TMyArray);
var I: Integer;
begin
  SetLength(arr1, 10);
  for I := Low(arr1) to High(arr1) do
    arr1[I] := IntToStr(I);
  SetLength(arr2, 20);
  for I := Low(arr2) to High(arr2) do
    arr2[I] := IntToStr(I);
end;

or write Test3 like this:
type
  TMyArray = array of string;
procedure Test3(var arr1, arr2: TMyArray);
var I: Integer;
begin
  Test2(arr1);
  SetLength(arr2, 20);
  for I := Low(arr2) to High(arr2) do
    arr2[I] := IntToStr(I);
end;



0
 
LVL 25

Expert Comment

by:epasquier
Comment Utility
Geert is right on what you are looking for.
He is so good at interpreting fuzzy questions ;o)
And if all the others where also using VAR keyword, Geert explained WHY.
He is sooo close to Genius now !

His Test2 procedure is the simplest example of what you need.
If you need more help, you'll have to be more specific about how you actually want to fill your array
0
 
LVL 14

Expert Comment

by:systan
Comment Utility
I think I have no room to answer question here in delphi zone, I better see some in c#.
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
>>epasquier
i used to have a manager who gave me an analysis on a 5x5cm piece of paper
like this:
  lbl designer SATO
  + security flow
  oracle db

are you jealous of me being so close to genius ?

 




0
 
LVL 25

Expert Comment

by:epasquier
Comment Utility
systan : I admit that the field is a bit overcrowded with regard to the number of questions, but what best way to learn and improve could you imagine other than keep trying and see how others are thinking, interacting, and ultimately finding the best answer possible ? That is team work.

If you go have a look how it is in C# zone, I'll be glad if you one day post a topic in Delphi Zone just to share your feelings about the C# zone : level of askers, of experts, nb of questions/day... And compare with Delphi zone
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
>>systan
you could do like cyberkiwi ... post in *all* the zones :)
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
>>epasquier, get back to work
or you'll break my all time record in delphi TA
0
 
LVL 25

Expert Comment

by:epasquier
Comment Utility
@Geert : jealous ? not at all ! I only took the opportunity to give you credits for your continuous work. You've been here longer than me, and I have been at some point like an iron ball chained at your feet, getting in your way for easy points. Pretty much the same as aflarin is doing now :o)

I suppose that is the order of things here, some new experts get excited by the challenge, they came here first because they had time, and then reality comes in the way and we have to earn some money at some point, so we calm down and let some room to newcomers.

I'm glad you are almost there to the biggest title a Delphi expert could dream of (really, there is missing one or even 2 ranks between Genius and Savant...That's just impossible to reach 10Mpts in Delphi in a lifetime).

I always knew you would do it before me. If aflarin does not get in my way, I'll try to join you as the fifth (does that not remind you of something?)
0
 
LVL 25

Expert Comment

by:epasquier
Comment Utility
>>epasquier, get back to work
or you'll break my all time record in delphi TA

Now, THAT is my intention :o))
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
>>HenryM2
sorry for cluttering up your post
but sometimes, we just can't help ourselves
There is just no Delphi Chat corner, just a lounge for everything, but no one monitors that

(does that not remind you of something?)
You want me to give a party with lots of beer ?

Yeah, you and lately aflarin are stealing a lot of easy poinx !
Fwiw, you both are only half as competitive as ciuly and ziolko were
They had/have the extra of being cleanup volunteers
I also asked to be cleanup volunteer ... still waiting ...
0
 
LVL 14

Expert Comment

by:DragonSlayer
Comment Utility
Hmm... am I too late to join the chat? LoL
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
chat ? yeah, you'r too late :)


0
 
LVL 58

Expert Comment

by:cyberkiwi
Comment Utility
>> you could do like cyberkiwi ... post in *all* the zones :)

Hm.. was that supposed to imply something?  I actually do Delphi for work.

Anyway, I cannot seem to link the question to Geert's solution, notwithstanding epasquier's endorsement thereof.  Maybe I need some beer.
0
 

Author Comment

by:HenryM2
Comment Utility
Sorry got interrupted with another problem, back now.
I think the Array names SourceArra and DestArray cased some confusion and perhaps made my question "Fuzzy" hece the perception that Procedure2 has to handle both Arrays at the same time.

I need only process the information in ONE of the arrays at a time, thus I want to process and load data into SourceArray OR DestArray, depending on which one the calling Procedure need the data loaded into.
0
 
LVL 14

Expert Comment

by:systan
Comment Utility
Geert, Epasquier;
lol, you guys are  all delphi genius.

Thanks

Back to the problem of HendryM2,

Listening...
0
 
LVL 58

Expert Comment

by:cyberkiwi
Comment Utility
And hence my Proc2 only has One array input...
I read it this way - you want to say "SourceArray" in a string as the array name, but in Delphi, you just pass a reference to the array?

procedure Proc1(Var SourceArray, DestArray : array of String);
begin
  // do something
  Proc2(SourceArray); // or DestArray
  // do something else
end;

Procedure Proc2(Var anArray: array of String);
begin
  // do something
end;
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
HenryM2 ...
That didn't really unfuzzy the fuzziness.

0
 
LVL 25

Expert Comment

by:epasquier
Comment Utility
Yes, Geert sorted that already, wouldn't you think ? That's much clearly said though.

Here is a  solution that summarize all the above hints

So, does it works for you or you are needing something else ?
Type

 TStringArray=Array of String;



Procedure DisplayStrings(StrList:TStringArray);

Var

 Str:String;

 i:integer;

begin

 Str:=Format('Array has %d elements',[Length(StrList)]);

 for i:=Low(StrList) to High(StrList) do Str:=Str+#13#10+StrList[i];

 ShowMessage(Str);

end;



procedure LoadStrings(Var StrList:TStringArray;NbItems,Offset:integer);

Var i:integer;

begin

 SetLength(StrList,NbItems);

 for i:=Low(StrList) to High(StrList) do StrList[i]:=IntToStr(i+Offset);

end;



procedure Procedure1;

Var

 A1,A2:TStringArray;

begin

 LoadStrings(A1,5,10);

 LoadStrings(A2,10,100);

 DisplayStrings(A1);

 DisplayStrings(A2);

end;

Open in new window

0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
i guess you want to want to make a decision based on the caller of the procedure ?

if so,
you will need to provide some kind of hanger (handle) to check who's calling ...

like a onClick event attached to Button1 and Button2:

procedure TForm1.OnButtonClick(Sender: TObject);
begin
  if Sender = Button1 then
    Test2(SourceArr)
  else
    Test2(DestArr);
end;

Are you looking for something like this ?

0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
>>epasquier,
sorry if this is taken in a direction which you hadn't thought of yet ...

:)
0
 

Author Comment

by:HenryM2
Comment Utility
Thanks for all contributed so far.  Yes Geert Gruwes this is what I want.  I think a global declaration for SourceArray and DestArray will be better.  Thus Procedure1 has to call Procedure2 and pass a reference to Procedure2(SourceArray) or Procedure2(DestinationArray);
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
global ?
ouch ... that will start a new discussion ... but while we are at it ...

you should consider the scope of those variables
i think you don't really need global

do you care to clarify a little more what the goal is
you have abstracted a little too much i think

the problem is like a database, you can normalize it completely
but for performance reasons, the last step is somewhat denormalizing it :)
0
 
LVL 58

Expert Comment

by:cyberkiwi
Comment Utility
Option 3 then.  We have blast off.  Glad to help.

3 options:
1,Procedure2 will be an internal procedure to Procedure1
2,SourceArray/DestArray is passed directly to Procedure2
3,SourceArray, DestArray are declared globally.

begin
  // do something
  Proc2(SourceArray); // or Proc2(DestArray)
  // do something else
end;
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
you are somewhat limiting cyberkiwi ...
there are a lot more options, i'm sure of that

consider the path the comments have made this question follow
0
 
LVL 58

Expert Comment

by:cyberkiwi
Comment Utility
I am always open to be educated.
Set aside methods like storing a pointer to (pointer to SourceArray) in a component Tag and passing the component reference and extracting the tag and casting to (pointer to array of string).

How would you get Procecure2 visibility of SourceArray?

(1)
Procedure Proc1();
var SourceArray, DestArray: array of string;
var isSource: boolean;
  Procedure Proc2();
  begin
    //if isSource then ... work on SourceArray else DestArray
  end;
begin
  // do something
  isSource := True;
  Proc2();
end;

(2)
Procedure Proc2(var inputArray: array of string);

Procedure Proc1();
var SourceArray, DestArray: array of string;
var isSource: boolean;
begin
  Proc2(SourceArray); // local var to Proc1 passed directly to Proc2
end;

(3)
var SourceArray, DestArray: array of string; // globally

Procedure Proc2(var inputArray: array of string);

procedure Proc1();
begin
  Proc2(SourceArray); // global var passed to Proc2
end;
0
 

Author Comment

by:HenryM2
Comment Utility
I hope the simple code here shows what I am trying to do.  This does not work as the  I suspect the Array Of String in the parameters of Procedure2 is out of place I need to add the Type
 TStringArray=Array of String;
somewhere? But where?  Sorry, I am a little new on the Type thing, is this what they call Type Casting?

The example may also explain why I think a global declaration of the Arrays may be better.  How does the VAR passing the information back effect speed?

procedure TMainFrm.Procedure2(ItemRecordNo :Byte; Var ArrayName : Array Of String);
Begin
  SetLength(ArrayName, 2);

  if ItemRecordNo = 1 then
  ArrayName[1] := 'Come'
  else
  ArrayName[1] := 'Go';
End;

procedure TMainFrm.WriteEquipPropertiesToURS;
Var SourceArray, DestArray : Array Of String;
    RecordNo : LongWord;
Begin
 Procedure2(1, SourceArray);
  Label1.Caption := SourceArray[1]; // Returns 'Come' in SourceArry[1]

  Procedure2(2, DestArray);
  Label2.Caption := DestArray[1]; // Returns 'Go' in DestArray[1]
End;
 
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
i think filling in the array's is NOT the problem here

it's determining what to fill in based on who's calling

it's the who's calling which is the problem

the declaration of the array's is just scope problem
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
can you explain without using code ?

is this similar to problem of incoming/outgoing traffic in a factory ?
0
 

Author Comment

by:HenryM2
Comment Utility
Procedure1 has the Arrays declared in it (Or globally if need be)
 Var SourceArray, DestArray : Array Of String;

Then Procedure1 has to call Procedure2 passing it an address of where to fetch the data from and then depending on where that data is from, it must go into SourceArray or DestArray inside Procedure1.

Procedure1 then goes ahead and compares the data in SourceArray with the data in DestArray.
0
 
LVL 58

Expert Comment

by:cyberkiwi
Comment Utility
procedure TMainFrm.Procedure2(WhereFrom :Byte; Var ArrayName : Array Of String);
Begin
  SetLength(ArrayName, 2);  // for this to work going back to caller, VAR is needed for proc param

  if <WhereFrom ... test> then
   //Update ArrayName from "where to fetch the data"
  else
   //Update ArrayName from "somewhere else to fetch the data"
End;

procedure TMainFrm.WriteEquipPropertiesToURS;
Var SourceArray, DestArray : Array Of String;
    RecordNo : LongWord;
Begin
 // ..somehow set up SourceArray
 // ..somehow set up DestArray

 if <.. some condition ..> then
   Procedure2(<fetch loc 1>, SourceArray)
 else
   Procedure2(<fetch loc 2>, DestArray);

 // compares the data in SourceArray with the data in DestArray.
End;
 
0
 

Author Comment

by:HenryM2
Comment Utility
The problem with:
procedure TMainFrm.Procedure2(WhereFrom :Byte; Var ArrayName : Array Of String);
Begin
  SetLength(ArrayName, 2);  // for this to work going back to caller, VAR is needed for proc param

The compiler generates an Incompatible types error on SetLenght here.
0
 
LVL 58

Assisted Solution

by:cyberkiwi
cyberkiwi earned 167 total points
Comment Utility
Wasn't watching too closely.
2nd comment (from aflarin) has this covered.  Create a custom type.

type
  TStringArray = array of string;

procedure TMainFrm.Procedure2(WhereFrom :Byte; Var ArrayName : TStringArray);
Begin
  SetLength(ArrayName, 2);  // for this to work going back to caller, VAR is needed for proc param

  if <WhereFrom ... test> then
   //Update ArrayName from "where to fetch the data"
  else
   //Update ArrayName from "somewhere else to fetch the data"
End;

procedure TMainFrm.WriteEquipPropertiesToURS;
Var SourceArray, DestArray : TStringArray;
    RecordNo : LongWord;
Begin
 // ..somehow set up SourceArray
 // ..somehow set up DestArray

 if <.. some condition ..> then
   Procedure2(<fetch loc 1>, SourceArray)
 else
   Procedure2(<fetch loc 2>, DestArray);

 // compares the data in SourceArray with the data in DestArray.
End;
 
0
 

Author Comment

by:HenryM2
Comment Utility
Where exactly do you put the
type
  TStringArray = array of string;

When I add this under the Type declarations, I get 1 Error, from the compiler, with message
[DCC Fatal Error] F2039 Could not create output file 'C:\Site Designer IV\RunTime\SiteDesignerIV.exe'  
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
anywhere in a general unit

off course you'll have to add it to the uses clause
all procedures/functions/methods using that type will need to know that unit or type declaration
only declare it once, or you'll have other conflicts
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
that error is because the app was still running
hit Ctrl-F2 first for a naughty close of the app ...
0
 

Author Comment

by:HenryM2
Comment Utility
Oeps, thanks, forgot the ap was runing on in the back ground from a previous compilation.
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
epasquier would say ...
it takes a genius to see that !
0
 

Author Closing Comment

by:HenryM2
Comment Utility
Thanks to all who contributed.  This was actually not so difficult but ended up in some interesting detours to get to the answer and at least I learned quit a bit.
0
 
LVL 25

Expert Comment

by:epasquier
Comment Utility
> it takes a genius to see that !
I would not say that. But it definitely took too much guessing to answer this question
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

How to remove superseded packages in windows w60 or w61 installation media (.wim) or online system to prevent unnecessary space. w60 means Windows Vista or Windows Server 2008. w61 means Windows 7 or Windows Server 2008 R2. There are various …
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now