Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Все, что вы не знали, но хотели бы узнать о Delphi N8


Выпуск №8

Раздел: Язык Программирования Delphi

Подраздел: Работа с битами +

работа с массивами

 

Уважаемый подписчик,

О чем будет следующий раздел - решать вам.

Варианты:

VCL

Системные функции и Winapi

Базы данных

Работа с файловой системой

Репортинг, работа с принтером

Работа с сетью, Интернетом, протоколами

Работа с графикой, мультимедиа

 

Ваши предложения высылайте на

formyreferal@rambler.ru

В этом выпуске:

Проверка - установлен ли определенный бит?
Установка бита в единицу
Установка бита в ноль
Переключение состояния бита с единицы на ноль и наоборот
Пример чтения данных по битовой маске из значения
Примеры работы с динамическими массивами
Массив в Delphi
Работа с большими массивами
Использование многомерного массива
Массив без ограничения типа и размера
Как удалить одно значение из динамического массива?
Операции над числовыми массивами
Использование PHP-like операций с массивами
Сохранение и загрузка двумерного динамического масива

Проверка - установлен ли определенный бит?  

Проверка - установлен ли определенный бит?

function IsBitSet(Value: cardinal; BitNum : byte): boolean;
begin
  result:=((Value shr BitNum) and 1) = 1
end;
...
if IsBitSet(43691,1then //установлен (равен 1)

Установка бита в единицу  


Установка бита в единицу

function BitOn(const val: longint; const TheBit: byte): LongInt;
begin
  Result := val or (1 shl TheBit);
end;
 

Установка бита в ноль  

Установка бита в ноль

function BitOff(const val: longint; const TheBit: byte): LongInt;
begin
  Result := val and ((1 shl TheBit) xor $FFFFFFFF);
end;
 

Переключение состояния бита с единицы на ноль и наоборот  


Переключение состояния бита с единицы на ноль и наоборот

function BitToggle(const val: longint; const TheBit: byte): LongInt;
begin
  Result := val xor (1 shl TheeBit);
end;
 

Пример чтения данных по битовой маске из значения  

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

procedure
 TForm1.Button1Click(Sender: TObject);
const
  Col: Word = $ABCD;
var
  R,
  G,
  B: Byte;
begin
  R := Byte(Col shr 8div 8// первые 5 бит
  G := ((Byte(Col shr 8and $7) * 8or (Byte(Col) div $20); // Вторые 6 бит
  B := Byte(Col) and $1F// третьи 5 бит
end;
Примеры работы с динамическими массивами  


Очень простой пример...
const
  MaxBooleans = (High(Cardinal) - $Fdiv 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?

Да. Для начала вам необходимо создать тип массива, использующего самый большой размер, который вам, вероятно, может понадобиться. В действительности, при создании типа никакой памяти не распределяется. Вот когда вы создаете переменную этого типа, тогда компилятор пытается распределить для вас необходимую память. Вместо этого создайте переменную, являющуюся указателем на этот тип. Этим вы заставите компилятор распределить лишь четыре байта, необходимые для размещения указателя.

Прежде, чем вы сможете пользоваться массивом, вам необходимо распределить для него память. Используя AllocMem, вы можете точно управлять выделяемым размером памяти. Для того, чтобы определить необходимое количество байт, которые вы должны распределить, просто умножьте размер массива на размер отдельного элемента массива. Имейте в виду, что самый большой блок, который вы сможете распределить в любой момент в 16-битной среде равен 64Kб. Самый большой блок, который вы можете в любой момент распределить в 32-битной среде равен 4Гб. Для определения максимального числа элементов, которые вы можете иметь в вашем конкретном массиве (в 16-битной среде), разделите 65,520 на размер отдельного элемента. Например: 65520 div SizeOf(LongInt)

Пример объявления типа массива и указателя:

type
  ElementType = LongInt;

const
  MaxArraySize = (65520 div SizeOf(ElementType));
(* в 16-битной среде *)

type
  MyArrayType = array[1..MaxArraySize] of ElementType;

var
  P: ^MyArrayType;

const
  ArraySizeIWant: Integer = 1500;

Затем, для распределения памяти под массив, вы могли бы использоваться следующую процедуру:

procedure AllocateArray;
begin
  if ArraySizeIWant <= MaxArraySize then
    P := AllocMem(ArraySizeIWant * SizeOf(LongInt));
end;

Не забывайте о том, что величина ArraySizeIWant должна быть меньше или равна MaxArraySize.

Вот процедура, которая с помощью цикла устанавливает величину каждого члена:

procedure AssignValues;
var
  I: Integer;
begin
  for I := 1 to ArraySizeIWant do
    P^[I] := I;
end;

Имейте в виду, что вам необходимо самому организовать контроль допустимого диапазона. Если вы распределили память для массива с пятью элементами, и пытаетесь назначить какое-либо значение шестому, вы получите ошибку и, возможно, порчу памяти.

Помните также о том, что после использования массива всю распределенную память необходимо освободить. Вот пример того, как избавиться от этого массива:

procedure DeallocateArray;
begin
  P := AllocMem(ArraySizeIWant * SizeOf(LongInt));
end;

Ниже приведен пример динамического массива:

unit Unit1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls;

type
  ElementType = Integer;

const
  MaxArraySize = (65520 div SizeOf(ElementType));
{ в 16-битной среде }

type
{ Создаем тип массива. Убедитесь в том, что вы установили
максимальный диапазон, который вам, вероятно, может понадобиться. }

  TDynamicArray = array[1..MaxArraySize] of ElementType;
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
{ Private declarations }
  public
{ Public declarations }
  end;

var
  Form1: TForm1;
{ Создаем переменную типа указатель на ваш тип массива. }
  P: ^TDynamicArray;

const
{ Это типизированные константы. В действительности они
являются статическими переменными, инициализирующимися
во время выполнения указанными в исходном коде значениями.
Это означает, что вы можете использовать типизированные
константы точно также, как и любые другие переменные.
Удобство заключается в автоматически инициализируемой величине. }

  DynamicArraySizeNeeded: Integer = 10;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
{ Распределяем память для нашего массива. Будь внимательны
и распределяйте размер, в точности необходимый для размещения нового массива.
Если вы попытаетесь записать элемент, выходящий за допустимый диапазон,
компилятор не ругнется, но объект исключения вам обеспечен. }

  DynamicArraySizeNeeded := 500;
  P := AllocMem(DynamicArraySizeNeeded * SizeOf(Integer));
{ Как присвоить значение пятому элементу массива. }
  P^[5] := 68;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
{ Вывод данных. }
  Button1.Caption := IntToStr(P^[5]);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
{ Освобождаем распределенную для массива память. }
  FreeMem(P, DynamicArraySizeNeeded * SizeOf(Integer));
end;

end.
 


Вот "демо-модуль", демонстрирующий три различных способа (далеко не все) создания динамических массивов. Все три способа для распределения достаточного количества памяти из кучи используют 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..1000of 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.
 


Массив, который может менять свой размер во время работы программы, нужен тогда, когда неизвестно количество элементов на стадии разработки программы. Например, Вам не известен размер изображения, которое нужно будет поместить в память.

Этот динамический массив основан на массиве Delphi. Поэтому обращение к нему быстро и удобно. Тип TArray – это массив нужного типа. 128 элементов можно заменить любым другим числом, хоть 0. Повлиять это может только на отладку программы, так как Delphi выведет (если уместится) именно это количество элементов. PArray – это указатель на TArray. При обращении к элементам массива для Delphi главное, чтобы этот элемент существовал в памяти, то есть, чтобы под него была выделена память. А проверять, находится ли номер нужного элемента между 0 и 127 Delphi не будет.

Главным методом объекта является SetCount. Он сделан таким образом, что при изменении количество элементом старые данные не теряются, а новые элементы всегда обнуляются.

Процедура Reset обнуляет все существующие элементы.

Для того чтобы сделать этот массив, например, массивом целых чисел нужно поменять все double на integer или еще что-то.

Если Ваша программа часто обращается к элементам массива, то имеет смысл создать переменную типа PArray и присвоить ей адрес данных (поле p динамического массива), а дальше обращаться к ней, как к самому обыкновенному массиву. Только не забудьте обновлять эту переменную при изменении количества элементов.

type
  TForm1 = ...
    ...
  end;

  TArray = array [0..127of double;
  PArray = ^TArray;
  TDynArray = object
    p: PArray;
    count: integer;
    constructor Create(ACount: integer); { инициализация }
    procedure SetCount(ACount: integer); { установка количества
                                           элементов }

    procedure Reset; { обнуление данных }

    destructor Destroy; { уничтожение }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

constructor TDynArray.Create(aCount: integer);
begin
  p := nil;
  count := 0;
  SetCount(ACount);
end;

procedure TDynArray.SetCount(ACount: integer);
var
  np: PArray;
begin
  if count = ACount then Exit;
  if p = nil then begin { память не была выделена }

    if ACount <= 0 then begin { новое количество элементов
                                в массиве равно 0 }

      count := 0;
    end else begin  { новое количество элементов в массиве
                      больше 0 }

      GetMem(p, ACount * sizeof(double)); { выделение памяти }
      fillchar(p^, ACount * sizeof(double), 0); { обнуление данных }
      count := ACount;

    end;
  end else begin
    if ACount <= 0 then begin { новое количество элементов в
                                массиве равно 0 }

      FreeMem(p, count * sizeof(double)); { освобождение памяти }
      count := 0;
    end else begin
      GetMem(np, ACount * sizeof(double)); { выделение памяти }

      if ACount > count then begin { требуется увеличить
                                     количество элементов }

        move(p^, np^, count * sizeof(double)); { перемещение
                                старых данных на новое место }

        fillchar(np^[count], (ACount - count) * sizeof(double),
          0); { обнуление новых элементов массива }
      end else begin

        move(p^, np^, ACount * sizeof(double)); { перемещение 
                           части старых данных на новое место }

      end;
      FreeMem(p, count * sizeof(double)); { освобождение старой
                                            памяти }

      p := np;
      count := ACount;
    end;
  end;
end;

procedure TDynArray.Reset;
begin
  fillchar(p^, count * sizeof(double), 0); { обнуление данных }

end;

destructor TDynArray.Destroy;
begin
  SetCount(0);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  a: TDynArray;
  i: integer;
  s: string;
begin
  a.Create(3);
  a.p[0] := 10;
  a.p[1] := 20;
  { второй элемент не указывается, но вследствии обнуления
    при создании массива он равен 0 }

  s := 'Элементы в массиве:';
  for i := 0 to a.count - 1 do

    s := s + #13#10 + IntToStr(i+1) + ': ' + FloatToStr(a.p[i]);
  ShowMessage(s);

  a.SetCount(4);
  a.p^[3] := 50;
  { значения первых элементов не теряются }
  s := 'Элементы в массиве:';
  for i := 0 to a.count - 1 do
    s := s + #13#10 + IntToStr(i+1) + ': ' + FloatToStr(a.p[i]);
  ShowMessage(s);

  a.Destroy;
end;
Массив в Delphi  

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

type
  VArray: array[1..1of double;

var
  X: ^VArray;
  NR, NC: Longint;

begin
  NR := 10000;
  NC := 100;
  if AllocArray(pointer(X), N * Sizeof(VArray)) then exit;
  SetV(X^, NC, 200053.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;

 



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

    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) динамическими сложными массивами и эти функции показали отличный результат.


 


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

(*

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

unit DynArray;

interface

uses
  SysUtils;

type
  TDynArrayBaseType = double;

const
  vMaxElements = (High(Cardinal) - $Fdiv 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 < 1then
    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 < 1or (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 < 1or (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 < 1or (row > fRows) then
    raise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]);
  if (column < 1or (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 < 1or (row > fRows) then
    raise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]);
  if (column < 1or (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]: 51);
      writeln;
    end;
  writeln;
  writeln('Перемещение');
  for col := 1 to M.Columns do
    begin
      for row := 1 to M.Rows do
        write(M[row, col]: 51);
      writeln;
    end;
  M.Free;
end.
 
Работа с большими массивами 

Распределите память кучи с помощью GetMem. Если вы имеете:

var
  a, b: array[0..30000]: Integer;

то попробуйте:

type
  TBigArray = array[0..30000of Integer;

var
  a, b: ^TBigArray;

и во внешнем блоке сделайте:

GetMem(a, SizeOf(TBigArray));
GetMem(b, SizeOf(TBigArray));

Также необходимо применять указатели на память вместо ссылок, например взамен:

a[0] := xxx; 

необходимо использовать

a^[0] := xxx; 

Использование многомерного массива  


type RecType = integer; {<-- здесь задается тип элементов массива}

const MaxRecItem = 65520 div sizeof(RecType);

type = MyArrayType = array[0..MaxRecItem] of RecType;
type = MyArrayTypePtr = ^MyArrayType;

var MyArray: MyArrayTypePtr;
begin
  ItemCnt := 10{количество элементов массива, которые необходимо распределить}
  GetMem(MyArray, ItemCnt * sizeof(MyArray[1])); {распределение массива}
  MyArray^[3] := 10{доступ к массиву}
  FreeMem(MyArray, ItemCnt * sizeof(MyArray[1])); {освобождаем массив после работы с ним}
end;
 

Массив без ограничения типа и размера  



//к примеру опишем свой тип
type

  MyType = record
    zap1: longword;
    zap2: char;
    zap3: string[10];
  end;

//опишем НЕОГРАНИЧЕННЫЙ массив переменный типа MyType
//хотя, может использоваться абсолютно любой
var
  m: array of MyType;

  ....

procedure TForm1.Button1Click(Sender: TObject);
var i: byte;
begin
  for i := 0 to 9 do // нумерация элементов начинается с нуля!

    begin
      SetLength(m, Length(m) + 1); // увеличение длины массива на 1
      m[i].zap1 := i; //  присвоение
      m[i].zap2 := chr(i); //          полям
      m[i].zap3 := inttostr(i); //              значений
    end;
end;

....

SetLength(m, 0); // освобождение памяти
end.

Как удалить одно значение из динамического массива?  


type
 
  TArrayString = array of string

procedure DeleteArrayIndex(var X: TArrayString; Index: Integer); 
begin 
  if Index > High(X) then Exit; 
  if Index < Low(X) then Exit; 
  if Index = High(X) then 
  begin 
    SetLength(X, Length(X) - 1); 
    Exit; 
  end
  Finalize(X[Index]); 
  System.Move(X[Index +1], X[Index], 
  (Length(X) - Index -1) * SizeOf(string) + 1); 
  SetLength(X, Length(X) - 1); 
end

// Example : Delete the second item from array a 
// Beispiel : Losche das 2. Element vom array a 

procedure TForm1.Button2Click(Sender: TObject); 
var 
  a: TArrayString; 
begin 
  DeleteArrayIndex(a, 2); 
end
Операции над числовыми массивами  

MaxIntValue    Возвращает наибольшее значение целочисленного массива.
MaxValue    Возвращает наибольшее значение числового массива.
Mean       Вычисляет среднее арифметическое всех значений массива.
MeanAndStdDev Вычисляет среднее арифметическое всех значений массива, и среднее отклонение.
MinIntValue    Возвращает наименьшее значение целочисленного массива.
MinValue    Возвращает наименьшее значение числового массива.
MomentSkewKurtosis Вычисляет среднее значение, дисперсию, отклонение и периодичность.
Norm       Возвращает Евклидову норму для всех значений массива.
PopnStdDev    Вычисляет среднеквадратичное отклонение для совокупности данных.
PopnVariance    Вычисляет дисперсию совокупности данных.
StdDev    Вычисляет стандартное среднеквадратичное отклонение элементов массива.
Sum       Вычисляет сумму значений всех элементов числового массива.
SumInt       Вычисляет сумму значений всех элементов целочисленного массива.
SumOfSquares Вычисляет сумму квадратов всех элементов числового массива.
SumsAndSquares Возвращает сумму элементов и сумму квадратов всех элементов числового массива.
TotalVariance    Вычисляет статистическую дисперсию.
Variance    Вычисляет типовую дисперсию всех значений массива.
Использование PHP-like операций с массивами  

//Some Array-functions like in PHP.

type

  ArrOfStr = array of string;

implementation

function explode(sPart, sInput: string): ArrOfStr;
begin
  while Pos(sPart, sInput) <> 0 do 
  begin
    SetLength(Result, Length(Result) + 1);
    Result[Length(Result) - 1] := Copy(sInput, 0,Pos(sPart, sInput) - 1);
    Delete(sInput, 1,Pos(sPart, sInput));
  end;
  SetLength(Result, Length(Result) + 1);
  Result[Length(Result) - 1] := sInput;
end;

function implode(sPart: string; arrInp: ArrOfStr): string;
var 
  i: Integer;
begin
  if Length(arrInp) <= 1 then Result := arrInp[0]
  else 
  begin
    for i := 0 to Length(arrInp) - 2 do Result := Result + arrInp[i] + sPart;
    Result := Result + arrInp[Length(arrInp) - 1];
  end;
end;

procedure sort(arrInp: ArrOfStr);
var 
  slTmp: TStringList; 
  i: Integer;
begin
  slTmp := TStringList.Create;
  for i := 0 to Length(arrInp) - 1 do slTmp.Add(arrInp[i]);
  slTmp.Sort;
  for i := 0 to slTmp.Count - 1 do arrInp[i] := slTmp[i];
  slTmp.Free;
end;

procedure rsort(arrInp: ArrOfStr);
var 
  slTmp: TStringList; 
  i: Integer;
begin
  slTmp := TStringList.Create;
  for i := 0 to Length(arrInp) - 1 do slTmp.Add(arrInp[i]);
  slTmp.Sort;
  for i := 0 to slTmp.Count - 1 do arrInp[slTmp.Count - 1 - i] := slTmp[i];
  slTmp.Free;
end;

Сохранение и загрузка двумерного динамического масива  

type

  T2DBooleanArray = array of array of Boolean;

procedure Save2DBooleanArray(const A: T2DBooleanArray; S: TStream);
var
  writer: TWriter;
  i: Integer;
begin
  Assert(Assigned(S));
  writer := TWriter.Create(S, 8096);
  try
    writer.WriteInteger(Length(A));
    for i := 0 to Length(A) - 1 do
    begin
      writer.WriteInteger(Length(A[i]));
      writer.Write(A[i, 0], Length(A[i]) * sizeof(A[i, 0]));
    end{ For }
  finally
    writer.Free;
  end{ Finally }
end;

procedure Load2DBooleanArray(var A: T2DBooleanArray; S: TStream);
var
  reader: TReader;
  i, numrows, numcols: Integer;
begin
  Assert(Assigned(S));
  reader := TReader.Create(S, 8096);
  try
    numrows := reader.ReadInteger;
    SetLength(A, numrows);
    for i := 0 to numrows - 1 do
    begin
      numcols := reader.ReadInteger;
      SetLength(A[i], numcols);
      reader.Read(A[i, 0], numcols * sizeof(A[i, 0]));
    end{ For }
  finally
    reader.Free;
  end{ Finally }
end;
 

 

 

 

Сайт рассылки Здесь

Так же можете посетить несколько сайтов для заработка в Интернете:

Hit&Host

 

Raskrutim.ru

 

WmSearch

 


В избранное