• Массивы
  • Динамические массивы
  • Массив в Delphi
  • Паскаль

    Массивы

    Динамические массивы

    Очень простой пример…

    Const MaxBooleans = (High(Cardinal) – $F) div sizeof(boolean);

    Type

     TBoolArray = array[1..MaxBooleans] of boolean;

     PBoolArray = ^TBoolArray;

    Var

     B: PBoolArray;

     N: integer;

    BEGIN

     N:= 63579;

     {= получение памяти под динамический массив.. =}

     GetMem(B, N*sizeof(boolean));

     {= работа с массивом… =}

     B^[3477]:= FALSE;

     {= возвращение памяти в кучу =}

     {$IFDEF VER80}

      FreeMem(B, N*sizeof(boolean));

     {$ELSE}

      FreeMem(B);

     {$ENDIF}

    END.

    Массив в 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}

     try

      GetMem(V, N);

     except

      ShowMessage('ОШИБКА выделения памяти. Размер:' + 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  =  CLASS

     Private

      fDimension: TDynArrayNDX;

      fMemAllocated: word;

      Function  GetElement(N: TDynArrayNDX): TDynArrayBaseType;

      Procedure SetElement(N: TDynArrayNDX; const NewValue: TDynArrayBaseType);

     Protected

      Elements : PArrayElements;

     Public

      Constructor Create(NumElements : TDynArrayNDX);

      Destructor Destroy; override;

      Procedure Resize(NewDimension : TDynArrayNDX); virtual;

      Property dimension: TDynArrayNDX read fDimension;

      Property Element[N : TDynArrayNDX] : TDynArrayBaseType read GetElement write SetElement; default;

     END;


    Const

     vMaxMatrixColumns = 65520 div sizeof(TDynArray);

     {= построение матрицы класса с использованием массива объектов TDynArray =}


    Type

     TMatrixNDX  =  1..vMaxMatrixColumns;

     TMatrixElements  =  array[TMatrixNDX] of TDynArray;

     {= каждая колонка матрицы будет динамическим массивом =}

     PMatrixElements  =  ^TMatrixElements;

     {= указатель на массив указателей… =}

     TDynaMatrix  =  CLASS

     Private

      fRows          : TDynArrayNDX;

      fColumns       : TMatrixNDX;

      fMemAllocated  : longint;

      Function GetElement(row: TDynArrayNDX; column: TMatrixNDX): TDynArrayBaseType;

      Procedure SetElement(row: TDynArrayNDX; column: TMatrixNDX; const NewValue: TDynArrayBaseType);

     Protected

      mtxElements: PMatrixElements;

     Public

      Constructor Create(NumRows : TDynArrayNDX; NumColumns : TMatrixNDX);

      Destructor Destroy; override;

      Property rows: TDynArrayNDX read fRows;

      Property columns: TMatrixNDX read fColumns;

      Property Element[row : TDynArrayNDX; column : TMatrixNDX] : TDynArrayBaseType read GetElement write 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) then raise 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) then raise 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) then raise 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 do BEGIN

      mtxElements^[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 do BEGIN

      dec(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) then raise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]);

     if (column < 1) OR (column > fColumns) then raise 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) then raise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]);

     if (column < 1) OR (column > fColumns) then raise 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 do for col:= 1 to M.Columns do M[row, col]:= row + col/10;

     writeln('Матрица');

     for row:= 1 to M.Rows do BEGIN

      for col:= 1 to M.Columns do write(M[row, col]:5:1);

      writeln;

     END;

     writeln;

     writeln('Перемещение');

     for col:= 1 to M.Columns do BEGIN

      for row:= 1 to M.Rows do write(M[row, col]:5:1);

      writeln;

     END;

     M.Free;

    END.







     


    Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх