Pascal


11. Обработка массивов

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

Как обращаться к отдельным элементам массива и оперировать с ними нам уже известно.

Единственная операция, которая возможна с массивом как с единым целым, это присваивание значений одного массива другому, при условии, что оба массива имеют совершенно одинаковый тип. Например, если
а, b: array [1 .. 43] of real;
и в прграмме было определено значение массива a (т.е. всем его элементам были присвоены конкретные значения), то для присваивания массиву b точно такого же значения (понимаемого, опять же, как набор значений его элементов) достаточно выполнить оператор присваивания:

b := a;

Никаких других действий с массивами в целом в Паскале не предусмотрено. Более того если описать массивы не в одной и той же строке:
а: array [1 .. 43] of real;
b: array [1 .. 43] of real;
то при попытке выполнить ту же команду присваивания
b := a
;
транслятор, уже не воспринимая эти массивы, как имеющие в точности один и тот же тип, выдаст ошибку: "Type mismatch."

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


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

Ввод

Пусть, напимер, в программе "участвует" массив, описанный следующим образом:
v: array [3 .. 7] of integer;

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

read(v[3]);
read(v[4]);
read(v[5])
;
read(v[6])
;
read(v[7]);
или
readln(v[3]);
readln(v[4]);
readln(v[5])
;
readln(v[6])
;
readln(v[7])
;

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

Легко заметить, что общий вид указанных команд

read(v[i]);
или
readln(v[i]);
где i = 3, 4,..., 7.

Теперь понятно как записать обе последовательности команд с помощью цикла:

for i:=3 to 7 do read(v[i]);
или
for i:=3 to 7 do readln(v[i]);

Вот так одной строкой можно организовать в программе ввод массива. А сколько строк прогаммы необходимо, чтобы ввести двумерный массив?


Вывод

Здесь все очень похоже. Тот же массив можно вывести на экран с помощью одного из циклов:

for i:=3 to 7 do write(v[i]);
или
for i:=3 to 7 do writeln(v[i]);

И опять различие между этими вариантами только в том, что во втором случае значения на экране будут располагаться в столбик, а в первом - в строку, причем вплотную друг к другу (например так: 231356789074345678). Чтобы в сделать выводимые значения "читаемыми", нужно в первый вариант внести небольшие изменения:

for i:=3 to 7 do write(v[i],'  ');
-
Между элементами будут выводиться пробелы
или
 
for i:=3 to 7 do write(v[i]:6);
-
Каждому значению будут отведены свои 6 знакомест


Наконец обратимся к вопросу о выводе на экран двумерного (прямоугольного) массива.
Если надо вывести на экран массив, описанный как
t: array [1 .. 6, 4 .. 7] of integer;
то, сообразив, что в нем всего 24 элемента, можно вывести их в одну строку или столбец (как это сделать?) Однако, нагляднее было бы вывести массив в виде, аналогичном следующей таблице:

4
5
6
7
1
t[1,4]
t[1,5]
t[1,6]
t[1,7]
2
t[2,4]
t[2,5]
t[2,6]
t[2,7]
3
t[3,4]
t[3,5]
t[3,6]
t[3,7]
4
t[4,4]
t[4,5]
t[4,6]
t[4,7]
5
t[5,4]
t[5,5]
t[5,6]
t[5,7]
6
t[6,4]
t[6,5]
t[6,6]
t[6,7]

Как вывести на экран одну строку этой таблицы (например, третью) мы уже видели:
for j:=4 to 7 do write(t[3,j]:6);
Поскольку после вывода каждой строки следует перевести курсор на новую строку, добавляем после цикла
writeln;. Итак, для вывода на экран i-ой строки таблицы (i=1,2,...,6) необходимы команды
for j:=4 to 7 do write(t[i,j]:6);
writeln;
Осталось повторить это при всех возможных значениях i (от 1 до 6). Получаем вложенные циклы:
for i:=1 to 6 do
  begin
     for j:=4 to 7 do write(t[i,j]:6);

     writeln
      
end;
Отметим, что во внешнем цикле изменяется номер строки таблицы, а во внутреннем - номер столбца. А что будет, если сделать наоборот:
for j:=4 to 7 do
  begin
     for i:=1 to 6 do write(t[i,j]:6);

     writeln
      
end; ?