Советы по Delphi

       

Массив в Delphi


Раздел 1

Вот несколько функций для операций с двухмерными массивами. Самый простой путь для создания собственной библиотеки. Процедуры SetV и GetV позволяют читать и сохранять элементы массива VArray (его Вы можете объявить как угодно). Например:

type
VArray : Array[1..1] of double;var
X : ^VArray;NR, NC : Longint;
begin
NR := 10000;NC := 100;if AllocArray(pointer(X), N*Sizeof(VArray)) then exit;SetV(X^, NC, 2000, 5, 3.27); { X[2000,5] := 3.27 }end;

function AllocArray(var V : pointer; const N : longint) : Boolean;
begin {распределяем память для массива V размера N}
tryGetMem(V, N);exceptShowMessage('ОШИБКА выделения памяти. Размер:' + IntToStr(N));Result := True;exit;end;FillChar(V^, N, 0); {в случае включения длинных строк заполняем их нулями}Result := False;end;

procedure SetV(var X : Varray;const N,ir,ic : LongInt;const value :
double);
begin {заполняем элементами двухмерный массив X размером ? x N : X[ir,ic] := value}
X[N*(ir-1) + ic] := value;end;

function GetV(const X : Varray; const N, ir,ic : Longint) : double;
begin {возвращаем величины X[ir,ic] для двухмерного массива шириной N столбцов}
Result := X[N*(ir-1) + ic];end;

Раздел 2

Самый простой путь - создать массив динамически



Myarray := GetMem(rows * cols * sizeof(byte,word,single,double и пр.)

сделайте функцию fetch_num типа

function fetch_num(r,c:integer) : single;

result := pointer + row + col*rows

и затем вместо myarray[2,3] напишите

myarray.fetch_num(2,3)

поместите эти функции в ваш объект и работа с массивами станет пустячным делом. Я экспериментировал с многомерными (вплоть до 8) динамическими сложными массивами и эти функции показали отличный результат.

Раздел 3

Вот способ создания одно- и двухмерных динамических массивов:

(*
---- модуль для создания двух очень простых классов обработки динамических массивов-- TDynaArray : одномерный массив-- TDynaMatrix : двумерный динамический массив--*)

unit DynArray;

INTERFACE

uses

SysUtils;
Type
TDynArrayBaseType = double;
Const
vMaxElements = (High(Cardinal) - $f) div sizeof(TDynArrayBaseType);{= гарантирует максимально возможный массив =}

Type
TDynArrayNDX = 1..vMaxElements;TArrayElements = array[TDynArrayNDX] of TDynArrayBaseType;{= самый большой массив TDynArrayBaseType, который мы может объявить =}PArrayElements = ^TArrayElements;{= указатель на массив =}
EDynArrayRangeError = CLASS(ERangeError);
TDynArray = CLASSPrivatefDimension : TDynArrayNDX;fMemAllocated : word;Function GetElement(N : TDynArrayNDX) : TDynArrayBaseType;Procedure SetElement(N : TDynArrayNDX; const NewValue : TDynArrayBaseType);ProtectedElements : PArrayElements;PublicConstructor Create(NumElements : TDynArrayNDX);Destructor Destroy; override;Procedure Resize(NewDimension : TDynArrayNDX); virtual;Property dimension : TDynArrayNDXread fDimension;Property Element[N : TDynArrayNDX] : TDynArrayBaseTyperead GetElementwrite SetElement;default;END;
Const
vMaxMatrixColumns = 65520 div sizeof(TDynArray);{= построение матрицы класса с использованием массива объектов TDynArray =}
Type
TMatrixNDX = 1..vMaxMatrixColumns;TMatrixElements = array[TMatrixNDX] of TDynArray;{= каждая колонка матрицы будет динамическим массивом =}PMatrixElements = ^TMatrixElements;{= указатель на массив указателей... =}
TDynaMatrix = CLASSPrivatefRows : TDynArrayNDX;fColumns : TMatrixNDX;fMemAllocated : longint;Function GetElement( row : TDynArrayNDX;column : TMatrixNDX) : TDynArrayBaseType;Procedure SetElement( row : TDynArrayNDX;column : TMatrixNDX;const NewValue : TDynArrayBaseType);ProtectedmtxElements : PMatrixElements;PublicConstructor Create(NumRows : TDynArrayNDX; NumColumns : TMatrixNDX);Destructor Destroy; override;Property rows : TDynArrayNDXread fRows;Property columns : TMatrixNDXread fColumns;Property Element[row : TDynArrayNDX; column : TMatrixNDX] : TDynArrayBaseTyperead GetElementwrite SetElement;default;END;
IMPLEMENTATION

(*
---- методы TDynArray--*)
Constructor TDynArray.Create(NumElements : TDynArrayNDX);
BEGIN {==TDynArray.Create==}inherited Create;fDimension := NumElements;GetMem( Elements, fDimension*sizeof(TDynArrayBaseType) );fMemAllocated := fDimension*sizeof(TDynArrayBaseType);FillChar( Elements^, fMemAllocated, 0 );END; {==TDynArray.Create==}
Destructor TDynArray.Destroy;
BEGIN {==TDynArray.Destroy==}FreeMem( Elements, fMemAllocated );inherited Destroy;END; {==TDynArray.Destroy==}
Procedure TDynArray.Resize(NewDimension : TDynArrayNDX);
BEGIN {TDynArray.Resize==}if (NewDimension < 1) thenraise EDynArrayRangeError.CreateFMT('Индекс вышел за границы диапазона : %d', [NewDimension]);Elements := ReAllocMem(Elements, fMemAllocated, NewDimension*sizeof(TDynArrayBaseType));fDimension := NewDimension;fMemAllocated := fDimension*sizeof(TDynArrayBaseType);END; {TDynArray.Resize==}
Function TDynArray.GetElement(N : TDynArrayNDX) : TDynArrayBaseType;
BEGIN {==TDynArray.GetElement==}if (N < 1) OR (N > fDimension) thenraise EDynArrayRangeError.CreateFMT('Индекс вышел за границы диапазона : %d', [N]);result := Elements^[N];END; {==TDynArray.GetElement==}
Procedure TDynArray.SetElement(N : TDynArrayNDX; const NewValue : TDynArrayBaseType);
BEGIN {==TDynArray.SetElement==}if (N < 1) OR (N > fDimension) thenraise EDynArrayRangeError.CreateFMT('Индекс вышел за границы диапазона : %d', [N]);Elements^[N] := NewValue;END; {==TDynArray.SetElement==}
(*
---- методы TDynaMatrix--*)
Constructor TDynaMatrix.Create(NumRows : TDynArrayNDX; NumColumns : TMatrixNDX);
Var col : TMatrixNDX;BEGIN {==TDynaMatrix.Create==}inherited Create;fRows := NumRows;fColumns := NumColumns;{= выделение памяти для массива указателей (т.е. для массива TDynArrays) =}GetMem( mtxElements, fColumns*sizeof(TDynArray) );fMemAllocated := fColumns*sizeof(TDynArray);{= теперь выделяем память для каждого столбца матрицы =}for col := 1 to fColumns doBEGINmtxElements^[col] := TDynArray.Create(fRows);inc(fMemAllocated, mtxElements^[col].fMemAllocated);END;END; {==TDynaMatrix.Create==}
Destructor TDynaMatrix.Destroy;
Var col : TMatrixNDX;BEGIN {==TDynaMatrix.Destroy;==}for col := fColumns downto 1 doBEGINdec(fMemAllocated, mtxElements^[col].fMemAllocated);mtxElements^[col].Free;END;FreeMem( mtxElements, fMemAllocated );inherited Destroy;END; {==TDynaMatrix.Destroy;==}
Function TDynaMatrix.GetElement( row : TDynArrayNDX;
column : TMatrixNDX) : TDynArrayBaseType;BEGIN {==TDynaMatrix.GetElement==}if (row < 1) OR (row > fRows) thenraise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]);if (column < 1) OR (column > fColumns) thenraise EDynArrayRangeError.CreateFMT('Индекс столбца вышел за границы диапазона : %d', [column]);result := mtxElements^[column].Elements^[row];END; {==TDynaMatrix.GetElement==}
Procedure TDynaMatrix.SetElement( row : TDynArrayNDX;
column : TMatrixNDX;const NewValue : TDynArrayBaseType);BEGIN {==TDynaMatrix.SetElement==}if (row < 1) OR (row > fRows) thenraise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]);if (column < 1) OR (column > fColumns) thenraise EDynArrayRangeError.CreateFMT('Индекс столбца вышел за границы диапазона : %d', [column]);mtxElements^[column].Elements^[row] := NewValue;END; {==TDynaMatrix.SetElement==}

END.

----Тестовая программа для модуля DynArray----

uses DynArray, WinCRT;

Const
NumRows : integer = 7;NumCols : integer = 5;
Var
M : TDynaMatrix;row, col : integer;BEGIN
M := TDynaMatrix.Create(NumRows, NumCols);for row := 1 to M.Rows dofor col := 1 to M.Columns doM[row, col] := row + col/10;writeln('Матрица');for row := 1 to M.Rows doBEGINfor col := 1 to M.Columns dowrite(M[row, col]:5:1);writeln;END;writeln;writeln('Перемещение');for col := 1 to M.Columns doBEGINfor row := 1 to M.Rows dowrite(M[row, col]:5:1);writeln;END;M.Free;END.
[000025]



Содержание раздела