11. Массивы

Массивы в Object Pascal во многом схожи с аналогичными типами данных в других языках программирования. Отличительная особенность массивов заключается в том, что все их компоненты суть данные одного типа (возможно, структурированного). Эти компоненты можно легко упорядочить и обеспечить доступ к любому из них простым указанием его порядкового номера, например:

var
  m: array [0..255] of Single;
  d: array [0..9] of Char;
begin
  …
  d[3] := 'a';
  m[17] := Ord(d[3])/10.0;end;

Объявление массива имеет следующий синтаксис:

<переменная>: array [<начало>..<конец>] of <тип данных>

Тип данных массива в свою очередь тоже может быть массивом. Таким образом можно описать n-мерный массив:

var
  Matrix2d: array [0..9] of array [0..7] of Integer;
  Matrix3d: array [0..9] of array [0..7] of array [0..10] of Char;
begin
  Matrix2d[0][1] := 10;			// Обращение к элементу
  Matrix3d[0][0][7] := 'J';		// массива.
end;

Сокращенная запись многомерного массива, а также указание порядкового типа в качестве размерности, в Pascal Script не поддерживается.

Пример:

var
  Arr2d: array [0..2,0..4] of Integer;		// Не поддерживается
  Arr: array [Byte] of Char;			// Не поддерживается
begin
  Arr2d[1, 2] := 2;				// Не поддерживается
end;

С помощью оператора присваивания можно копировать элементы массива в другой массив.

var
  a, b: array [1..5] of Integer;
  c: array [1..5] of Integer;
  d: array [1..7] of Integer;
begin
  …
  b := a;
  c := a; // Компилятор пропустит, но во время выполнения произойдет ошибка
  d := a; // несоответствия типовend;

Для массивов не определены операции отношения, сравнивать массивы можно только поэлементно:

for i := 0 to 5 do
  if a[i] <> b[i] then

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

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

var
  a: array of Integer;
  a2: array of array of Double;
  a3: array of array of array of String;

Объявление динамического массива отличается тем, что не указываются границы массива в квадратных скобках. Для работы с динамическим массивом его надо инициализировать, т. е. задать длину. Делается это процедурой SetLength.

SetLength(a, 10);

При инициализации массиву выделяется память, и массив заполняется нулями. Нижняя граница динамического массива всегда равна 0, верхняя будет на единицу меньше его длины (в примере будет 9). Узнать длину массива можно функцией Length:

for i := 0 to Length(a)1 do

Работа с элементами динамического массива ничем не отличается от работы с элементами статического массива. Для работы с многомерным массивом надо задать размер всем его измерениям:

SetLength(a2, 10);
for i := 0 to Length(a2)1 do
  SetLength(a2[i], 7);
 
SetLength(a3, 5);
for i := 0 to Length(a3)1 do
begin
  SetLength(a3[i], 7);
  for j := 0 to Length(a3[i])1 do
    SetLength(a3[i][j], 3);
end;

Так как элемент многомерного динамического массива сам является массивом, то в одном измерении могут быть массивы разной длины:

SetLength(a[0], 1);
SetLength(a[1], 2);
SetLength(a[2], 3);

Фактически идентификатор динамического массива ссылается на указатель, содержащий адрес первого байта памяти, выделенной для массива. Поэтому присваивание одного массива другому приводит к копированию ссылки на область памяти, занятую массивом, а не самого массива.

var
  a, b: array of Integer;
begin
  SetLength(a, 2);
  a[0] := 1;
  a[1] := 2;
  b := a;
  b[2] := 3; // Фактически произойдет изменение элемента массива a – a[2]=b[2]
end;

Для копирования массива вам придется выделять память для нового массива и копировать массив поэлементно. При изменении длины уже инициированного динамического массива по какому-либо его измерению сначала резервируется нужная для размещения нового массива память, затем элементы старого массива переносятся в новый, после чего освобождается память, выделенная прежнему массиву. Чтобы сократить дополнительные затраты времени, связанные с изменением границ большого динамического массива, следует сразу создать массив максимальной длины. После окончания работы с массивом нужно освободить память занятую массивом. Для этого длина массива уменьшается до 0.

SetLength(a, 0);
// Сначала освобождаем память, занятую массивами-элементами двухмерного массива
for i := 0 to Length(a2) - 1 do
  SetLength(a2[i], 0);
// Теперь можно укоротить сам двухмерный массив.
SetLength(a2, 0);