2007. május 21., hétfő
Creating "Dynamic" Arrays
Problem/Question/Abstract:
Is it possible to re-size arrays at runtime?
Answer:
I came across an example of how to do one. The author is Ben Licht, 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:
{This unit demonstrates how to implement a dynArray}
unit U;
interface
uses
SysUtils, WinTypes, WinProcs, Classes, Controls, Forms, Dialogs, StdCtrls;
type
TResizeArr = array[0..0] of string;
PResizeArr = ^TResizeArr;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
procedure DefineDynArray(var h: THandle; {Handle to mem pointer}
NumElements: LongInt; {Number of items in array}
var PArr: PResizeArr); {Pointer to array struct}
procedure TestDynArray;
implementation
{$R *.DFM}
{============================================================================
Procedure that defines the dynarray. Note that the THandle and Pointer to
the array are passed by reference. This enables them to be defined outside
the scope of this procedure.
============================================================================}
procedure DefineDynArray(var h: THandle; {Handle to mem pointer}
NumElements: LongInt; {Number of items in array}
var PArr: PResizeArr); {Pointer to array struct}
begin
{Allocate Windows Global Heap memory}
h := GlobalAlloc(GMEM_FIXED, NumElements * sizeof(TResizeArr));
PArr := GlobalLock(h);
end;
{============================================================================
Procedure that uses the DefineDynArray proc. This is pretty useless, but
provides a good example of how you can access the elements of the 'array'
once the array is defined.
============================================================================}
procedure TestDynArray;
var
MyArray: PResizeArr;
I: Integer;
str: string;
h: THandle;
begin
str := '';
DefineDynArray(h, 10, MyArray); {Define the 'array'}
for I := 0 to 9 do
MyArray^[I] := IntToStr(I);
for I := 0 to 9 do
str := str + MyArray^[I] + ',';
ShowMessage(str);
GlobalUnlock(h); {Must make a call to unlock the memory, then}
GlobalFree(h); {free the memory and invalidate the handle}
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TestDynArray;
end;
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.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése