Программирование на языке Delphi/§5
В общем случае массив — это структурированный тип данных, состоящий из некоторого числа элементов, имеющих один и тот же тип. В качестве элементов массива можно использовать любой другой ранее описанный тип, поэтому вполне правомерно существование массивов записей, массивов указателей, массивов строк, массивов массивов и т. д. Объявление массивов:
var
a:array[1..10] of integer;
b:array[1..20] of char;
Одномерные массивы
правитьЭлементами массива могут быть данные любого типа, включая структурированные. К необходимости применения массивов (прямого или опосредованного) мы приходим всегда, когда требуется связать и использовать ряд однотипных величин. При описания массива используются зарезервированные слова array и of. За словом array в квадратных скобках указывается диапазон или перечислимый(ordinal) тип, определяющий количество элементов массива. После слова of указывается тип элементов, образующих массив. Доступ к каждому элементу массива осуществляется с помощью индекса. Нельзя указывать значение индекса, не входящий в диапазон массива.
var
a:array[1..10]of integer;
begin
a[7]:=14;
a[2]:=11;
a[0]:=20; //Ошибка!
end.
В отличие от C-подобных языков(C/C++/Java/C#), в которых начальным индексом массива всегда служит нулевое целое, в Delphi при объявлении переменной-массива или типа-массива, указывается диапазон значений индекса, а не количество элементов. Это означает, что первым элементом массива может быть элемент с индесом, отличным от нуля.
Заполнение массивов происходит поэлементно, обычно использую оператор for:
{$APPTYPE CONSOLE}
var
a:array[1..100] of integer;
i,j:integer;
begin
for i:=1 to 100 do //Заполнение массива случайными числами.
a[i]:=random(9)+1; //ф-ция random возвращает псевдослучайное число в интервале 0..<параметр>-1
for i:=0 to 9 do begin //Вывод по 10 чисел на строку
for j:=1 to 10 do //Внутренний цикл
write(a[i*10+j],' ');
writeln(' ');
end;
readln;
end.
Допускается инициализация не-локальных переменных-массивов:
var t:array[1..3] of Integer=(1,2,3);
type TRec=record
s:string;
v:integer;
end;
var ra:array[1..2] of TRec=((s:'test';v:3), (s:'test2';v:4));
Другие примеры объявления массивов
procedure test4();
type TWorkingDays=(Monday,Tuesday,Wednesday,Thursday, Friday);
var ar:array[boolean]of integer;
ar2:array[TWorkingDays] of Cardinal;
ar3:array[Tuesday..Thursday] of Cardinal;
bl:boolean;
wd:TWorkingDays;
begin
RandSeed:=2;
for bl in [true,false] do begin
ar[bl]:=random(13);
end;
for wd := Monday to Friday do ar2[wd]:=random(100);
for wd :=Tuesday to Thursday do ar3[wd]:=random(4);
end;
Переменные-массивы, имеющие аналогичный, но не идентичный тип, вообще говоря, не являются совместимыми.
procedure test();
var tt,tt2:array[1..3] of Integer;//=(1,2,3);
tt3:array[1..3] of integer;
begin
tt[1]:=3;tt[2]:=4; tt[3]:=5;
tt2:=tt;//OK
tt3:=tt;//EROOR: Incompatible types
end;
Многомерные массивы
правитьЕсли в тип элемента массива есть другой массив, то образуется структура, которую принято называть многомерным массивом.
var
a:array[1..10]of array[1..20]of integer;
b:array[1..10,1..20]of integer;// то же, что и выше
Если при форме описания массива задан один индекс, массив называется одномерным, если два индекса — двумерным, если n индексов — n-мерным. Одномерный массив соответствует понятию линейной таблицы (вектора), двумерный — понятию прямоугольной таблицы (матрицы). Для доступа к элементам n-мерного массива нужно указывать n индексов:
var a:array[1..10,1..50]of integer;
begin
a[1,1]:=23;
a[4,25]:=0;
end.
Избегайте объявления (статических) массивов больших размерностей (общим размером более 4095 байт) в качестве локальных переменных, равно как и нескольких локальных массивов, общий размер которых превышает указанное значение.
Динамические массивы
правитьБывают ситуации, когда заранее трудно предположить, какой размер должен быть у массива. Например если необходимо считать файл: если массив будет слишком малым, то файл может не поместиться в нем, а если массив будет слишком большим, то он будет занимать много лишней памяти. Динамические массивы позволяют создавать массивы с заранее неизвестным количеством элементов. Кроме того, в отличие от вышеупомянутых статических массивов, динамические массивы всегда распределены в динамически выделяемых областях памяти("куче"/heap либо виртуальной памяти процесса).
var a:array of integer;
Для работы с динамическим массивом необходимо выделить ему память. Для этого используется функция setLength
var a:array of integer;
begin
setLength(a,20);//массив длиной 20 элементов, скорей всего займет 20*4 байт, не считая служебной информации.
end.
Первый параметр функции SetLength - переменная типа "динамический массив", второй - количество элементов. Счет элементов начинается с 0. Другими словами, динамические массивы всегда индексируются с нуля(в отличие от статических, в которых нижняя граница индекса указывается явно). Также возможно создание многомерных динамических массивов.
{$APPTYPE CONSOLE}
var
a:array of array of integer;
l1,l2,i,j:integer;
begin
writeln("Введите размер массива");
readln(l1); //Ввод размеров массива
readln(l2);
setlength(a,l1);
for i:=0 to l1-1 do
setLength(a[i],l2); //Инициализация массивов
for i:=0 to l1-1 do
for j:=0 to l2-1 do
a[i,j]:=random(10);
end.
Так как двумерный динамический массив представляет собой массив других динамических массивов, то их также необходимо инициализировать. Если статический многомерный массив всегда является прямоугольным, кубическим и так далее, то есть размерность массива массивов всегда одинакова, то для многомерного динамического массива это может быть неверным.
procedure Triangular();
var a:array of array of integer;//динамический двумерный массив
i,j,v:integer;
begin
SetLength(a, 3);// массив a состоит из 3 элементов-массивов
v:=1;
writeln('Triangular');
for i:=Low(a) to High(a) do begin//Системная функция High, примененная к переменной массиву(динамическому или статическому), возвратит наибольший индекс массива
// (в нашем случае 2)
// а Low - наименьший индекс массива. Поскольку, нижней границей для динамического массива является 0, то для динамического массива Low всегда будет возвращать 0
SetLength(a[i], i+1);// для первого элемента-массива размерность будет 1, то есть в нем будет лишь один элемент, для второго таких элементов будет 2 и так далее
for j:=Low(a[i]) to High(a[i]) do begin
a[i,j]:=v;
write(a[i,j],#$9);
Inc(v);//v:=v+1;
end;//for j
writeln('');
end;//for i
a:=nil;
end;//proc
вывод функции будет таким:
Triangular
1
2 3
4 5 6
Узнать длину динамического массива, можно вызовом функции Length(a), где a- переменная-динамический массив. Очевидно, для дин. массивов, тождесвенно равенство:
Length(a)=High(a)+1
Динамический массив в Delphi, подобен стандартной строке в том, что это указатель со встроенным подсчетом ссылок. Отличие же состоит в том, что он не обладает COW-семантикой; другими словами, копируя переменную-дин.массив в другую переменную того же типа, вы копируете указатель, но не сами данные, увеличиваете счетчик ссылок на единицу, и получаете псевдоним, а не копию. Модификация массива-источника, таким образом, модифицирует и массив-приемник, и наоборот, так как это один и тот же блок данных в памяти.
Удаление массива из памяти происходит тогда, когда разрешается последняя ссылка на массив: иными словами, когда переменной-дин. массиву присваивают значение nil, либо она выходит из области видимости(в случае локальных переменных), происходит неявное уменьшение счетчика ссылок на 1, и сравнение этого счетчика с 0. Если счетчик ссылок нулевой, то происходит финализация и освобождение памяти. Принудительно освободить занимаемую массивом память можно также посредством установки его длины в 0:
setLength(vAr,0);