Может ли кто мне подсказать как динамически создать массив записей
и получить доступ к отдельным элементам?
Определите тип массива, которым может содержать максимальное количество
записей, затем определите тип, являющийся указателем на массив. Идея заключается
в том, чтобы не создавать экземпляр самого большого массива; а вместо этого
использовать указательный тип и GetMem для распределения памяти для необходимого
вам количества записей.
Я разработал то, что я называю шаблоном массива переменной длины "для бедных
людей"...
|
|
unit %s;
{
-----------------------------------------------------------
ШАБЛОН МАССИВА ПЕРЕМЕННОЙ ДЛИНЫ
Вы можете использовать этот шаблон для создания массива
переменной длины любого типа данных.
Для того, чтобы превратить шаблон с модуль, прогоните его
через текстовый процессор, выполните во всем файле операцию
поиска/замены для замены знака процента на ваш тип данных.
-----------------------------------------------------------
} interface
const
%MaxCapacity = High( Cardinal )
div SizeOf( % ); type
T%Index = 0..%MaxCapacity - 1;
T%s = array[ T%Index ] of %;
P%s = ^T%s; function %sSize( Capacity: T%Index
): Cardinal; function Get%s( Capacity:
T%Index ): P%s;
function Resize%s( var
P: P%s;
OldCapacity, NewCapacity: T%Index
): P%s; procedure Free%s( var P: P%s;
Capacity: T%Index
);
implementation uses SysUtils;
function %sSize( Capacity: T%Index
): Cardinal; begin
Result := Capacity * SizeOf( %
); end;
function Get%s(
Capacity: T%Index ): P%s; begin
GetMem( Result, %sSize( Capacity
)); end;
function Resize%s( var P: P%s;
OldCapacity, NewCapacity: T%Index
): P%s; begin
ReAllocMem( P, %sSize( OldCapacity
), %sSize( NewCapacity
)); end;
procedure Free%s( var P: P%s;
Capacity: T%Index ); begin
FreeMem( P, %sSize( Capacity
));
P := nil; end;
end.
|
Приведенный выше модуль определяет тип массива и тип-указатель на массив,
далее я приведу четыре полезные подпрограммы для работы с ним.
Вот модуль, использующий после операции поиска и замены (см. выше) тип записи
'MyRecord', содержащий также определение этой записи. Поскольку "MyRecords" было
очень длинным для имени модуля, я укоротил его. Имейте в виду, что PMyRecords -
тип вашего переменного массива, если вы используете этот модуль.
|
|
unit
MyRecs; interface
type
MyRecord = record
AnInt: Integer;
AString: string[ 10 ];
end; const
MyRecordMaxCapacity = High( Cardinal ) div SizeOf( MyRecord
); type
TMyRecordIndex = 0..MyRecordMaxCapacity -
1;
TMyRecords = array[ TMyRecordIndex ] of
MyRecord;
PMyRecords = ^TMyRecords; function MyRecordsSize(
Capacity: TMyRecordIndex ): Cardinal; function GetMyRecords( Capacity:
TMyRecordIndex ): PMyRecords; function ResizeMyRecords( var P:
PMyRecords;
OldCapacity, NewCapacity: TMyRecordIndex ):
PMyRecords; procedure FreeMyRecords( var P: PMyRecords;
Capacity: TMyRecordIndex );
implementation uses
SysUtils;
function MyRecordsSize( Capacity: TMyRecordIndex ):
Cardinal; begin
Result := Capacity * SizeOf( MyRecord
); end;
function GetMyRecords( Capacity:
TMyRecordIndex ): PMyRecords; begin
GetMem( Result, MyRecordsSize( Capacity
)); end;
function ResizeMyRecords( var P:
PMyRecords;
OldCapacity, NewCapacity: TMyRecordIndex ):
PMyRecords; begin
ReAllocMem( P, MyRecordsSize( OldCapacity ),
MyRecordsSize( NewCapacity
)); end;
procedure FreeMyRecords( var P:
PMyRecords; Capacity: TMyRecordIndex ); begin
FreeMem( P, MyRecordsSize( Capacity ));
P := nil; end;
end.
|
Наконец, вот пример использования массива переменной длины. Помните, что
указатель должен использоваться с символом "^"...
|
|
procedure
TForm1.Button1Click( Sender: TObject ); var
P: PMyRecords; begin
P := GetMyRecords( 10 );
try
P^[ 0 ].AnInt := 2001;
P^[ 0 ].AString := 'Космическая одиссея';
finally
FreeMyRecords( P, 10 );
end; end; |
- Ed Jordan |