* * *

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

justnewbie

  • Full Member
  • ***
  • Posts: 129
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: 308
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

  • Full Member
  • ***
  • Posts: 129
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

  • Jr. Member
  • **
  • Posts: 59
  • I click a little.
    • TreeStructInfo - format for text and binary configuration files
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.

justnewbie

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

furious programming

  • Jr. Member
  • **
  • Posts: 59
  • I click a little.
    • TreeStructInfo - format for text and binary configuration files
Re: Populate a dynamic array
« Reply #5 on: March 25, 2018, 11:05:22 pm »
No, it can works bad – I miss something.

Nitorami

  • Sr. Member
  • ****
  • Posts: 308
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

  • Jr. Member
  • **
  • Posts: 59
  • I click a little.
    • TreeStructInfo - format for text and binary configuration files
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 »

Nitorami

  • Sr. Member
  • ****
  • Posts: 308
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

  • Jr. Member
  • **
  • Posts: 59
  • I click a little.
    • TreeStructInfo - format for text and binary configuration files
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

justnewbie

  • Full Member
  • ***
  • Posts: 129
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

  • Jr. Member
  • **
  • Posts: 59
  • I click a little.
    • TreeStructInfo - format for text and binary configuration files
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 »

jamie

  • Hero Member
  • *****
  • Posts: 762
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!

justnewbie

  • Full Member
  • ***
  • Posts: 129
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

  • Full Member
  • ***
  • Posts: 129
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 »

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus