Содержание
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);