Author: Lou Adler
Is it possible to re-size arrays at runtime?
Answer:
I came across an example of how to do one. The author is Ben
Lichtmailto:benl@panix.com, who presents an age-old Pascal method of creating a
dynamic array.
The trick is using a pointer to an array with a size of 1, then allocating memory
for the pointer by multiplying the number of items you want in the array by the
size of the array type.
Here's a sample unit I've adapted from his example:
1 {This unit demonstrates how to implement a dynArray}
2 unit U;
3
4 interface
5
6 uses
7 SysUtils, WinTypes, WinProcs, Classes, Controls, Forms, Dialogs, StdCtrls;
8
9 type
10 TResizeArr = array[0..0] of string;
11 PResizeArr = ^TResizeArr;
12 TForm1 = class(TForm)
13 Button1: TButton;
14 procedure Button1Click(Sender: TObject);
15 private
16 { Private declarations }
17 public
18 { Public declarations }
19 end;
20
21 var
22 Form1: TForm1;
23
24 procedure DefineDynArray(var h: THandle; {Handle to mem pointer}
25 NumElements: LongInt; {Number of items in array}
26 var PArr: PResizeArr); {Pointer to array struct}
27
28 procedure TestDynArray;
29
30 implementation
31 {$R *.DFM}
32
33 {============================================================================
34 Procedure that defines the dynarray. Note that the THandle and Pointer to
35 the array are passed by reference. This enables them to be defined outside
36 the scope of this procedure.
37 ============================================================================}
38
39 procedure DefineDynArray(var h: THandle; {Handle to mem pointer}
40 NumElements: LongInt; {Number of items in array}
41 var PArr: PResizeArr); {Pointer to array struct}
42 begin
43
44 {Allocate Windows Global Heap memory}
45 h := GlobalAlloc(GMEM_FIXED, NumElements * sizeof(TResizeArr));
46 PArr := GlobalLock(h);
47 end;
48
49 {============================================================================
50 Procedure that uses the DefineDynArray proc. This is pretty useless, but
51 provides a good example of how you can access the elements of the 'array'
52 once the array is defined.
53 ============================================================================}
54
55 procedure TestDynArray;
56 var
57 MyArray: PResizeArr;
58 I: Integer;
59 str: string;
60 h: THandle;
61 begin
62 str := '';
63 DefineDynArray(h, 10, MyArray); {Define the 'array'}
64 for I := 0 to 9 do
65 MyArray^[I] := IntToStr(I);
66 for I := 0 to 9 do
67 str := str + MyArray^[I] + ',';
68 ShowMessage(str);
69 GlobalUnlock(h); {Must make a call to unlock the memory, then}
70 GlobalFree(h); {free the memory and invalidate the handle}
71 end;
72
73 procedure TForm1.Button1Click(Sender: TObject);
74 begin
75 TestDynArray;
76 end;
77
78 end.
This is a perfect example of one of those programming things that take hours to figure out, but turn out to be amazingly simple. But I should point out that it might just be simpler to use a TList, which does all of the above, but has methods to insert and delete items. It's only limited by the amount of memory you have.
|