Библиотека программиста

«Если отладка - процесс удаления ошибок, то программирование должно быть процессом их внесения»

Э.Дейкстра

Главная страница > Язык Object Pascal > 9. Массивы

9. Массивы

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

По признаку размещения в памяти массивы подразделяются на статические (static) и динамические (dynamic).

Статические массивы. Эти массивы объявляются с помощью такого формата:

array [indexType 1 , ..., indexType n ] of baseType

Каждый из типов indexType должен быть порядкового типа, диапазон которого не должен превосходить 2 Гбайт.

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

Многомерные массивы являются массивами массивов, вследствие чего описание type TMatrix = array[1..10] of array[1..50] of Real; эквивалентно type TMatrix = array[1..10, 1..50] of Real. Подобным образом, переменная MyMatrix типа TMatrix может индексироваться как MyMatrix[2,45] или MyMatrix[2][45].

Стандартные функции Low и High возвращают для типа массив или переменной­ низшую и высшую границу для первого индекса массива. Функция Length возвращает число элементов массива в первой размерности. Например, для массива array [-5..5] функция Low вернет –5, а Length вернет значение 11.

Одномерный, статический, упакованный массив символов (Char) называется упакованной строкой (packed string). Упакованные строки совместимы с другими строковыми типами и упакованными строками, которые имеют то же число элементов. Тип массива array[0..x] of Char называется массивом символов с отсчетом от нуля (zero-based character array), используется для хранения строк с завершающим нулем и совместим со значениями типа PChar.

Пример для массивов символов:

Program TestCharArray;

{$APPTYPE CONSOLE}

uses SysUtils;

var

sAnsi : string;

sShort : shortstring;

cArr : array [0..1000] of char;

BEGIN

sAnsi:='Test';

WriteLn(sAnsi);

// cArr:=sAnsi; несовместимость типов

// cArr:=sShort; несовместимость типов

// cArr:=PChar(sAnsi); несовместимость типов

// cArr:=PChar(sShort); недопустимое приведение типа

cArr:='array [0..1000] of char';

WriteLn(cArr);

sAnsi:=cArr;

WriteLn(sAnsi);

// sShort:=cArr; несовместимость типов

sShort:=String(cArr);

WriteLn(sAnsi);

sShort:=ShortString(cArr);

WriteLn(sShort);

ReadLn;

END.

Динамические массивы. Эти массивы, впервые введенные в Delphi 4, не имеют фиксированного размера или длины. Память для них перераспределяется с помощью процедуры SetLength. Динамические массивы объявляются с использованием формата array of baseType, например

var MyFlexibleArray: array of Real;

При описании массива память для него не выделяется, но ее можно выделить так: SetLength(MyFlexibleArray, 20). Динамический массив всегда индексируется целочисленным типом и всегда с нуля, так что после приведенного примера первым элементом массива является MyFlexibleArray[0], а последним – MyFlexibleArray[19].

Попросту говоря, динамические массивы являются указателями, которые, подобно указателям на длинные строки PChar, могут индексироваться. Для освобождения памяти, выделенной массиву, просто присвойте его имени значение nil или вызовите процедуру Finalize.

Для динамических массивов нельзя применять операцию разыменования (^) или вызывать процедуры New и Dispose.

Если X и Y являются переменными одного типа динамический массив, оператор X := Yустанавливает для массива Х такую же длину, как и для массива Y, однако, в отличие от строк и статических массивов, не копирует элементы массива. Например, после выполнения кода

var

A, B: array of Integer;

begin

SetLength(A, 1);

A[0] := 1;

B := A;

B[0] := 2;

end;

значением элемента массива A[0] будет 2.

Присваивание значения элементу массива, например, MyFlexibleArray[2] := 7, не вызывает перераспределения памяти. Выход индекса за границу массива не контролируется на этапе компиляции программы, как сказано в документации к Delphi 5.0. На практике, по крайней мере в Delphi 6.0, выход индекса за границу массива контролируется на этапе выполнения программы, что весьма ценно.

При сравнении массивов сравниваются указатели, но не их содержимое.

Для усечения динамического массива можно использовать функцию Copy:

Function Copy(Vec; Index, Count: Integer): array;

Например, после выполнения оператора A := Copy(A, 5, 2) массив A будет содержать только два элемента.

К динамическим массивам можно применять также стандартные функции Length, High и Low. Length возвращает число элементов массива, High – наибольший индекс (Length–1), а Low –0. В случае массива нулевой длины High вернет –1.

Замечание. Описание формального параметра подпрограммы также может иметь вид array of baseType. Такие параметры называют открытыми массивами и никакого прямого отношения к динамическим массивам они не имеют.

Многомерные динамические массивы (multidimensional dynamic arrays).Для их объявления итеративно используется конструкция array of ... . Например, описание

type TMessageGrid = array of array of string;

var Msgs: TMessageGrid;

вводит двумерный массив строк. Для инициализации такого массива вызывается процедура SetLength с двумя целочисленными параметрами. После этого выражение Msgs[0,0] указывает на первый элемент такого массива.

Можно создавать такие многомерные динамические массивы, которые не являются прямоугольными. Для этого при первом вызове SetLength ей передается число элементов по первой размерности, например:

var Ints: array of array of Integer;

SetLength(Ints,10);

Этот код выделяет память для 10 строк, но не для столбцов. Далее можно выделить для каждой строки любое число столбцов, например, SetLength(Ints[2], 5). Теперь уже можно присваивать значения элементам третьей строки (индекс 2), даже если для столбцов остальных строк память еще не была выделена. Следующий пример иллюстрирует создание треугольной матрицы:

var

A : array of array of integer;

I, J : Integer;

begin

SetLength(A, 10);

for I := Low(A) to High(A) do

begin

SetLength(A[I], I+1);

for J := Low(A[I]) to High(A[I]) do

A[I,J] := (I+1)*10 + J + 1;

end;

end;

Пример повторного применения процедуры SetLength и использования трехмерного динамического массива:

Program DinArrTest;

{$APPTYPE CONSOLE}

uses SysUtils;

var

Arr : array of integer;

Arr3D : array of array of array of integer;

i,j,k,n1,n2,n3 : integer;

BEGIN

{проверка повторного применения процедуры SetLength }

SetLength(Arr,5);

for i:=0 to 4 do Arr[i]:=i;

SetLength(Arr,3);

for i:=0 to High(Arr) do

Write(Arr[i]:5); {0 1 2 }

WriteLn;

SetLength(Arr,6);

for i:=0 to High(Arr) do

Write(Arr[i]:5); {0 1 2 0 0 0}

WriteLn;

{операции с трехмерным массивом}

n1:=2; n2:=3; n3:=2;

SetLength(Arr3D,n1);

for i:=0 to n1-1 do

SetLength(Arr3D[i],n2);

for i:=0 to n1-1 do

for j:=0 to n2-1 do

SetLength(Arr3D[i,j],n3);

for i:=0 to n1-1 do

for j:=0 to n2-1 do

for k:=0 to n3-1 do

Arr3D[i,j,k]:=(i+1)*100+(j+1)*10+k+1;

for i:=0 to n1-1 do

begin

for j:=0 to n2-1 do

begin

for k:=0 to n3-1 do

Write(Arr3D[i,j,k]:5);

WriteLn;

end;

WriteLn;

end;

ReadLn;

END.

Результат выполнения программы:

0 1 2

0 1 2 0 0 0

111 112

121 122

131 132

211 212

221 222

231 232





<< Предыдущая статья
«8. Структурные типы»
Следующая статья >>
10. Записи