Определите тип массива, которым может содержать максимальное количество записей, затем определите тип, являющийся указателем на массив. Идея заключается в том, чтобы не создавать экземпляр самого большого массива; а вместо этого использовать указательный тип и 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 = recordAnInt: 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 );tryP^[ 0 ].AnInt := 2001;P^[ 0 ].AString := 'Космическая одиссея';finallyFreeMyRecords( P, 10 );end;end; |
- Ed Jordan [000990]