Recent

Author Topic: Populate a dynamic array  (Read 12863 times)

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Populate a dynamic array
« on: March 25, 2018, 10:28:47 pm »
I have a dynamic array (empty in the beginning) and I want to populate it with unknown number of elements. How should it be?
My bad code:

Code: Pascal  [Select][+][-]
  1. TValue = packed record
  2.     tvVal: integer;
  3.     tvString: string;  
  4.   end;
  5.  
  6.   tvArray = array of TValue;
  7.   pTVArray = ^tvArray;
  8.  
  9. // ...
  10.  
  11. procedure PopulateArray(var myArray: pTVArray);
  12. var i: integer;
  13.     counter: integer = 0;
  14. begin
  15.   for i := 0 to 100 do
  16.     begin
  17.       if {something} then
  18.       begin
  19.          inc(counter);
  20.          SetLength(myArray,counter);
  21.          myArray[counter-1].tvVal := i;
  22.          myArray[counter-1].tvString := 'Hi friend!';
  23.       end;
  24.     end;
  25. end;
« Last Edit: March 25, 2018, 10:34:34 pm by justnewbie »

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Populate a dynamic array
« Reply #1 on: March 25, 2018, 10:41:05 pm »
If you are a newbie then by all means use simple native pascal code and don't fuff with pointers. Why do you need pTVArray ? It's completely unnecessary.

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Populate a dynamic array
« Reply #2 on: March 25, 2018, 10:47:13 pm »
If you are a newbie then by all means use simple native pascal code and don't fuff with pointers. Why do you need pTVArray ? It's completely unnecessary.
I have to communicate between a DLL (written in FP) and MT4. This is why I need pointers (I guess). Example here (with some formatting noise): https://www.forexfactory.com/showthread.php?t=219576 (see "3. Giving the DLL access to all bars in the chart")

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Populate a dynamic array
« Reply #3 on: March 25, 2018, 10:53:29 pm »
First off, you must allocate memory for an array, before you try to set length of this array. Then, you need to set the length of array, and then, allocate memory for every array cell, before you write some data to them.

Below is a simple example – works correctly. Change the code for your purpose.

Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}{$LONGSTRINGS ON}
  2.  
  3. uses
  4.   HeapTrc;
  5.  
  6. type
  7.   PItem = ^TItem;
  8.   TItem = record
  9.     Value: Integer;
  10.     Text: String;
  11.   end;
  12.  
  13. type
  14.   PItems = ^TItems;
  15.   TItems = array of PItem;
  16.  
  17.   procedure PopulateItems(AItems: PItems);
  18.   var
  19.     LLength: Integer = 0;
  20.   begin
  21.     SetLength(AItems^, LLength + 1);
  22.  
  23.     New(AItems^[LLength]);
  24.     AItems^[LLength]^.Value := 100;
  25.     AItems^[LLength]^.Text := 'got it';
  26.   end;
  27.  
  28. var
  29.   LItems: PItems;
  30. begin
  31.   New(LItems);
  32.   PopulateItems(LItems);
  33.  
  34.   WriteLn('Value: ', LItems^[0]^.Value);
  35.   WriteLn('Text:  ', LItems^[0]^.Text);
  36.  
  37.   Dispose(LItems^[0]);
  38.   Dispose(LItems);
  39. end.
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Populate a dynamic array
« Reply #4 on: March 25, 2018, 10:55:43 pm »
Thank you, I will study it!

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Populate a dynamic array
« Reply #5 on: March 25, 2018, 11:05:22 pm »
No, it can works bad – I miss something.
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Populate a dynamic array
« Reply #6 on: March 25, 2018, 11:13:42 pm »
A dynamic array IS essentially already a pointer.
And setting the length does allocate the memory, no need to use "new" or GetMem.

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Populate a dynamic array
« Reply #7 on: March 25, 2018, 11:21:42 pm »
And setting the length does allocate the memory, no need to use "new" or GetMem.

No, using the New procedure is necessary. If you do not do this, you will get an SIGSEGV in SetLength.

Below is a more complex example. Works perfectly.

Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}{$LONGSTRINGS ON}
  2.  
  3. uses
  4.   HeapTrc, SysUtils;
  5.  
  6. type
  7.   PItem = ^TItem;
  8.   TItem = record
  9.     Value: Integer;
  10.     Text: String;
  11.   end;
  12.  
  13. type
  14.   PItems = ^TItems;
  15.   TItems = array of PItem;
  16.  
  17.   procedure PopulateItems(out AItems: PItems; ACount: Integer);
  18.   var
  19.     LItemIdx: Integer;
  20.   begin
  21.     New(AItems);
  22.     SetLength(AItems^, ACount);
  23.  
  24.     for LItemIdx := 0 to ACount - 1 do
  25.     begin
  26.       New(AItems^[LItemIdx]);
  27.  
  28.       AItems^[LItemIdx]^.Value := Random(100) + 1;
  29.       AItems^[LItemIdx]^.Text := Format('item no %d', [LItemIdx]);
  30.     end;
  31.   end;
  32.  
  33.   procedure DisposeItems(var AItems: PItems);
  34.   var
  35.     LItemIdx: Integer;
  36.   begin
  37.     for LItemIdx := 0 to High(AItems^) do
  38.       Dispose(AItems^[LItemIdx]);
  39.  
  40.     Dispose(AItems);
  41.     AItems := nil;
  42.   end;
  43.  
  44.   procedure PrintItems(AItems: PItems);
  45.   var
  46.     LItemIdx: Integer;
  47.   begin
  48.     for LItemIdx := 0 to High(AItems^) do
  49.       WriteLn('Value: ', AItems^[LItemIdx]^.Value, ', Text: ', AItems^[LItemIdx]^.Text);
  50.  
  51.     WriteLn();
  52.   end;
  53.  
  54. var
  55.   LItems: PItems;
  56. begin
  57.   Randomize();
  58.  
  59.   PopulateItems(LItems, 10);
  60.   PrintItems(LItems);
  61.   DisposeItems(LItems);
  62. end.

Examplary output:

Code: [Select]
Value: 76, Text: item no 0
Value: 29, Text: item no 1
Value: 59, Text: item no 2
Value: 32, Text: item no 3
Value: 87, Text: item no 4
Value: 38, Text: item no 5
Value: 16, Text: item no 6
Value: 2, Text: item no 7
Value: 98, Text: item no 8
Value: 95, Text: item no 9

Heap dump by heaptrc unit
109 memory blocks allocated : 2519/2736
109 memory blocks freed     : 2519/2736
0 unfreed memory blocks : 0
True heap size : 196608 (128 used in System startup)
True free heap : 196480
« Last Edit: March 25, 2018, 11:32:14 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

Nitorami

  • Sr. Member
  • ****
  • Posts: 481
Re: Populate a dynamic array
« Reply #8 on: March 25, 2018, 11:34:33 pm »
This works equally without any pointers.

Code: Pascal  [Select][+][-]
  1. type
  2.   TItem = record
  3.     Value: Integer;
  4.     Text: String;
  5.   end;
  6.  
  7. type
  8.   TItems = array of TItem;
  9.  
  10.   procedure PopulateItems(var AItems: TItems; ACount: Integer);
  11.   var
  12.     LItemIdx: Integer;
  13.   begin
  14.     SetLength(AItems, ACount);
  15.  
  16.     for LItemIdx := 0 to ACount - 1 do
  17.     begin
  18.  
  19.       AItems[LItemIdx].Value := Random(100) + 1;
  20.       AItems[LItemIdx].Text := Format('item no %d', [LItemIdx]);
  21.     end;
  22.   end;
  23.  
  24.   procedure DisposeItems(var AItems: TItems);
  25.   var
  26.     LItemIdx: Integer;
  27.   begin
  28.     for LItemIdx := 0 to High(AItems) do SetLength (AItems,0)
  29.   end;
  30.  
  31.   procedure PrintItems(const AItems: TItems);
  32.   var
  33.     LItemIdx: Integer;
  34.   begin
  35.     for LItemIdx := 0 to High(AItems) do
  36.       WriteLn('Value: ', AItems[LItemIdx].Value, ', Text: ', AItems[LItemIdx].Text);
  37.  
  38.     WriteLn();
  39.   end;
  40.  
  41. var
  42.   LItems: TItems;
  43. begin
  44.   Randomize();
  45.   PopulateItems(LItems, 10);
  46.   PrintItems(LItems);
  47.   DisposeItems(LItems);
  48. end.
  49.  

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Populate a dynamic array
« Reply #9 on: March 25, 2018, 11:46:07 pm »
 @Nitorami: yes, but @justnewbie wants to use pointers – let him play.  :D
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Populate a dynamic array
« Reply #10 on: March 26, 2018, 12:06:49 am »
@furious: justnewbie only needs a working method for communication between a DLL and MT4.  I'm searching for the simplest way.  :)
If there is any pointer-less method, just let me know.

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Populate a dynamic array
« Reply #11 on: March 26, 2018, 12:34:50 am »
Ok, so @Nitorami change my code and show how to do it without pointers.

Edit: If you don't need pointers, you can use following:

Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}{$LONGSTRINGS ON}
  2.  
  3. uses
  4.   HeapTrc, SysUtils;
  5.  
  6. type
  7.   TItem = record
  8.     Value: Integer;
  9.     Text: String;
  10.   end;
  11.  
  12. type
  13.   TItems = array of TItem;
  14.  
  15.   procedure PopulateItems(var AItems: TItems; ACount: Integer);
  16.   var
  17.     LItemIdx: Integer;
  18.   begin
  19.     SetLength(AItems, ACount);
  20.  
  21.     for LItemIdx := 0 to ACount - 1 do
  22.     begin
  23.       AItems[LItemIdx].Value := Random(100) + 1;
  24.       AItems[LItemIdx].Text := Format('item no %d', [LItemIdx]);
  25.     end;
  26.   end;
  27.  
  28.   procedure DisposeItems(var AItems: TItems);
  29.   begin
  30.     SetLength(AItems, 0);
  31.   end;
  32.  
  33.   procedure PrintItems(const AItems: TItems);
  34.   var
  35.     LItem: TItem;
  36.   begin
  37.     for LItem in AItems do
  38.       WriteLn('Value: ', LItem.Value, ', Text: ', LItem.Text);
  39.  
  40.     WriteLn();
  41.   end;
  42.  
  43. var
  44.   LItems: TItems;
  45. begin
  46.   Randomize();
  47.  
  48.   PopulateItems(LItems, 10);
  49.   PrintItems(LItems);
  50.   DisposeItems(LItems);
  51. end.

DisposeItems does not need a loop – you only need to change the size of the array once. PrintItems can use for in loop to improve code readability.
« Last Edit: March 26, 2018, 02:46:12 am by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: Populate a dynamic array
« Reply #12 on: March 26, 2018, 03:59:34 am »
I think a little more reading on the use of the MT4 dll is needed here..  >:(

Does this interface comply with a COM/OLE interface ?

you really need to know..

I suppose it could also be just a callback, but still you need to know....

if there is a function you are calling that is supplying a POINTER to a block of memory within the
MT4 Library, then you need to know this too!.... Because that would require you to assign a specific pointer
to a Records with a few variant fields in it or close to that anyways!
The only true wisdom is knowing you know nothing

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Populate a dynamic array
« Reply #13 on: March 26, 2018, 10:31:02 am »

Edit: If you don't need pointers ...

To be honest I really don't know whether I need pointers or not. In the example what I saw, there was pointer, so I think I need it.

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Populate a dynamic array
« Reply #14 on: March 26, 2018, 10:34:22 am »
@jamie: my knowledge is weak to it, I don't understand these things.
But, I could make a code that is able to send candle-data from MT4 to a DLL function and its result went back to the MT4.
« Last Edit: March 26, 2018, 11:23:05 am by justnewbie »

 

TinyPortal © 2005-2018