
Лекция 6
Инициализация массивов
const
A: array[1..7] of double = (1, 3, 5, 7, 9, 11, 13);
B: array[1..2, 1..4] of integer =
(
(3, 4, 1, 0),
(5, 2, 7, 6)
);
C: array[1..2, 1..3] of char =
(
(‘a’, ‘b’, ‘c’),
(‘x’, ’y’, ‘z’)
);
Инициализация записей
type
MyRecord1 = record
i, j: integer;
x: double;
s: string[7];
end;
MyRecord2 = record
mA: array[1..3, 1..3] of char;
S: MyRecord1;
end;
const
R1: MyRecord1 = (i: 4; j: 9; x: 3.14159; s: 'ABCDE');
R2: MyRecord2 = ( ??? );
Открытые массивы
var
B: array[3..7] of double;
procedure P(var A: array of double);
begin
WriteLN('High(A)=', High(A), ' A[High(A)[=', A[High(A)]:0:2);
WriteLN('Low(A)=', Low(A), ' A[Low(A)[=', A[Low(A)]:0:2);
ReadLN;
end;
begin
B[3] := 3; B[4] := 4; B[5] := 5; B[6] := 6; B[7] := 7;
P(B);
end.
Динамические массивы
Динамические массивы не имеют фиксированного размера. Память под массив выделяется, когда ему придается значение (!) или по отношению к нему применяется процедура SetLength.
<Объявление динамического массива> ::=
<Имя массива>: array of <Тип>
Переменная <Имя массива> в действительности является указателем, однако, знаком ^, процедурами New, Dispose пользоваться по отношению к этой переменной нельзя.
Процедура SetLength
procedure SetLength(var <Имя массива>; <Число элементов>: integer);
Под одномерный массив <Имя массива> выделяется место в памяти, объем которого задает <Число элементов>.
Диапазон индексов: 0 .. <Число элементов> - 1 .
Процедура Finalize
procedure Finalize(var <Имя массива>);
Память из-под переменной <Имя массива> высвобождается.
Альтернатива:
<Имя массива> := Nil;
Процедуру FreeMem применять не следует.
Пример 1.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
mA: array of char;
begin
SetLength(mA, 3);
mA[2] := 's';
writeln(mA[2]);
readln;
end.
Пример 2.
var
mA, mB: array of integer;
mC, mD: array [0..10] of integer;
begin
SetLength(mA, 11);
mA[0] := 1;
mB := mA; // Указатель mB стал указывать туда же, куда и указатель mA.
mB[0] := 2;
mC[0] := 1;
mD := mC; // В массив mD скопировано всё содержимое массива mC.
end.
Переменная mB есть указатель на тот же динамический массив, что и переменная mA. Значение mA[0] есть 2.
Оператор mB[11] := 2; не приводит к увеличению числа элементов массива до 12. Ответственность за выход за границы массива (и за всю тяжесть последствий) лежит на программисте.
Пример 3.
var
mA, mB: array of integer; // Динамические массивы
mC, mD: array[0..0] of integer; // Статические массивы
begin
mC[0] := 2; mD[0] := 2;
writeln(mC = mD); // True. Содержимое массивов одинаково.
SetLength(mA, 1); SetLength(mB, 1);
mA[0] := 2; mB[0] := 2;
writeln(mA = mB); // False. Содержимое массивов одинаково,
// а вот указатели на массивы НЕ равны.
writeln(mA[0] = mB[0]); // True. Эти элементы массивов равны.
end;
Пример 4.
var
i, n: integer;
mA: array of integer;
begin
n:=7; SetLength(mA, n); for i:=0 to n-1 do mA[i]:=i;
for i:=0 to n-1 do write(mA[i]:3); // 0 1 2 3 4 5 6
n:=4; SetLength(mA, n);
for i:=0 to n-1 do write(mA[i]:3); // 0 1 2 3
// Массив «подрезан» до 4 элементов. Эти элементы сохранили свои значения.
n:=8; SetLength(mA, n);
for i:=0 to n-1 do write(mA[i]:3); // 0 1 2 3 0 0 0 0
// Массив расширен до 8 элементов.
// Но нет гарантии, что новым элементам придается значение 0.
// Эти значения, вообще говоря, непредсказуемы.
readln;
writeln(Length(mA)); // 8
writeln(High(mA)); // 7
writeln(Low(mA)); // 0
Finalize(mA);
writeln(Length(mA)); // 0
writeln(High(mA)); // -1
writeln(Low(mA)); // 0
readln;
end.
Пример 5. Двумерные массивы (точнее, массивы массивов)
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
MyRowType = array of integer;
// MyRowType – указатель на массив элементов типа integer.
var
i, j: integer;
mA: array of MyRowType;
// mA – указатель на массив указателей (на массив элементов типа integer)
begin
SetLength(mA, 3); // Размещен в памяти массив указателей на строки матрицы.
// Сами строки пока в памяти не размещены.
for i := 0 to 2 do
SetLength(mA[i], 4);
// Размещены в памяти строки матрицы. Длина каждой строки – 4 числа.
for i := 0 to 2 do
for j := 0 to 3 do
mA[i][j] := 10 * (i + 1) + (j + 1);
// Допускается обращение mA[i, j]
for i := 0 to 2 do
begin
for j := 0 to 3 do
write(mA[i][j]:5);
writeln;
end;
for i := 0 to 2 do
Finalize(mA[i]);
// Память освобождена из-под строк матрицы.
// Указатели на строки пока доступны.
writeln;
for i := 0 to 2 do
SetLength(mA[i], i+4);
// Размещены в памяти новые строки «матрицы». Длины строки неодинаковы.
// Таким образом, «матрица» - не совсем верное определение.
// Правильнее говорить, что mA есть «Jagged Array» (зазубренный массив).
for i := 0 to 2 do
for j := 0 to i+3 do
mA[i][j] := 10*(i+1)+(j+1);
for i := 0 to 2 do
begin
for j := 0 to i+3 do write(mA[i][j]:5);
writeln;
end;
for i := 0 to 2 do Finalize(mA[i]);
// Память освобождена из-под строк матрицы.
Finalize(mA);
// Память освобождена и из-под указателей на строки.
readln;
end.