Динамические массивы 3
Автор: Robert Wittig
Вот "демо-модуль", демонстрирующий три различных способа (далеко не все)
создания динамических массивов. Все три способа для распределения достаточного
количества памяти из кучи используют GetMem, tList используют для добавления
элементов в список массива и используют tMemoryStream для того, чтобы
распределить достаточно памяти из кучи и иметь к ней доступ, используя поток.
Старый добрый GetMem вполне подходит для такой задачи при условии, что массив не
слишком велик (<64K).
PS. Я не стал ловить в коде исключения (с помощью блоков Try...Finally},
которые могли бы мне помочь выявить ошибки, связанные с распределением памяти. В
реальной системе вы должны быть уверены в своем грациозном владении
низкоуровневыми операциями с памятью.
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
{ Форма, демонстрирующая различные методы создания массива с }
{ динамически изменяемым размером. Разместите на форме четыре кнопки,}
{ компоненты ListBox и SpinEdit и создайте, как показано ниже, }
{ обработчики событий, возникающие при нажатии на кнопки. Button1, }
{ Button2 и Button3 демонстрируют вышеуказанных метода. Button4 }
{ очищает ListBox для следующего примера. }
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
unit Dynarry1;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Spin;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
SpinEdit1: TSpinEdit;
ListBox1: TListBox;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
type
pSomeType = ^SomeType;
SomeType = Integer;
procedure TForm1.Button1Click(Sender: TObject);
type
pDynArray = ^tDynArray;
tDynArray = array[1..1000] of SomeType;
var
DynArray: pDynArray;
I: Integer;
begin
{ Распределяем память }
GetMem(DynArray, SizeOf(SomeType) * SpinEdit1.Value);
{ Пишем данные в массив }
for I := 1 to SpinEdit1.Value do
DynArray^[I] := I;
{ Читаем данные из массива }
for I := SpinEdit1.Value downto 1 do
ListBox1.Items.Add('Элемент ' + IntToStr(DynArray^[I]));
{ Освобождаем память }
FreeMem(DynArray, SizeOf(SomeType) * SpinEdit1.Value);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
List: tList;
Item: pSomeType;
I: Integer;
begin
{ Создаем список }
List := tList.Create;
{ Пишем данные для списка }
for I := 1 to SpinEdit1.Value do
begin
{ Распределяем уникальный экземпляр данных }
New(Item);
Item^ := I;
List.Add(Item);
end;
{ Читаем данные из списка - базовый индекс списка 0, поэтому вычитаем из I единицу }
for I := SpinEdit1.Value downto 1 do
ListBox1.Items.Add('Элемент ' +
IntToStr(pSomeType(List.Items[I - 1])^));
{ Освобождаем лист }
for I := 1 to SpinEdit1.Value do
Dispose(List.Items[I - 1]);
List.Free;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
Stream: tMemoryStream;
Item: SomeType;
I: Integer;
begin
{ Распределяем память потока }
Stream := tMemoryStream.Create;
Stream.SetSize(SpinEdit1.Value);
{ Пишем данные в поток }
for I := 1 to SpinEdit1.Value do
{ Stream.Write автоматически отслеживает позицию записи,
поэтому при записи данных за ней следить не нужно }
Stream.Write(I, SizeOf(SomeType));
{ Читаем данные из потока }
for I := SpinEdit1.Value downto 1 do
begin
Stream.Seek((I - 1) * SizeOf(SomeType), 0);
Stream.Read(Item, SizeOf(SomeType));
ListBox1.Items.Add('Элемент ' + IntToStr(Item));
end;
{ Освобождаем поток }
Stream.Free;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
ListBox1.Items.Clear;
end;
end.
|
|