Рис.88 – Примеры простых переменных (слева) и массивов (справа)
Итак, массив – это собранные в одну команду переменные. Они получают общее на всех имя – имя своей команды. А внутри команды каждая переменная – элемент массива – обладает своим номером. Ну, чем не игроки?
Объявление массивов
Прежде, чем пользоваться массивом, его надо объявить: либо в секции VAR, либо через объявление пользовательского типа в секции TYPE.
Рассмотрим сначала первый способ, – объявим массив в секции VAR.
VAR Имя_Массива : ARRAY [<MIN>..<MAX>] OF <Тип элемента>
Здесь использована пара ключевых слов ARRAY… OF…, что переводится как «массив… из…». Имя массива – это обычный идентификатор, его программист придумывает сам; будем считать это имя названием команды переменных.
Справа, после двоеточия, указывают две характеристики массива: 1) диапазон для индексов и 2) тип элементов массива. Рассмотрим эти атрибуты массива подробней.
Диапазон для индексов определяет допустимые номера элементов внутри массива. Диапазон указывают в квадратных скобках после слова ARRAY, – это два выражения порядкового типа, условно обозначенные мною как MIN и MAX, они разделяются двумя точками. Говоря спортивным языком, здесь назначается диапазон номеров для «игроков команды».
После ключевого слова OF следует второй атрибут массива – тип данных для всех его элементов. Прибегнув вновь к спортивному языку, скажем, что здесь объявляют «вид спорта» для команды.
Вот пример объявления трех массивов: Names (фамилии), Ratings (оценки) и ChampShip (чемпионат).
VAR { объявления переменных-массивов }
{ 30 строковых переменных с фамилиями учеников класса }
Names : ARRAY [1..30] OF string;
{ 30 байтовых переменных с оценками учеников этого класса }
Ratings : ARRAY [1..30] OF byte;
{ 16 чисел с очками, набранными командами в чемпионате }
ChampShip : ARRAY [1..16] OF integer;
Как видите, массив можно составить из элементов любого типа. Так, массив Names содержит внутри себя 30 переменных строкового типа: Names[1], Names[2] и так далее (номера переменных указывают в квадратных скобках).
Объявление массивов в секции VAR не слишком удобно. Почему? Рассмотрим следующий пример.
var A : array [1..5] of integer;
B : array [1..5] of integer;
begin
A:= B; { здесь компилятор видит ошибку несовместимости типов}
end.
Мы объявили массивы A и B; на первый взгляд, это массивы одного типа, поскольку каждый из них содержит по пять целых чисел. Для однотипных переменных, включая массивы, Паскаль допускает операцию копирования. Например, оператором
A:=B
все элементы массива B копируются в элементы массива A. Увы, компилятор увидит здесь ошибку несовместимости типов. В чем дело? А в том, что он считает разнотипными массивы, объявленные в разных операторах. Даже если массивы совершенно одинаковы! Скажете, компилятор недостаточно умен? Может быть, но нам придётся как-то выкручиваться, и для этого есть два пути.
Во-первых, переменные A и B можно объявить в одном операторе.
var A, B : array [1..5] of integer;
Это устраняет проблему несовместимости типов.
Но есть и лучший способ – сначала объявить для массива пользовательский тип данных. Это делается в секции TYPE так:
TYPE Имя_Типа = ARRAY [<MIN>..<MAX>] OF <Тип элемента>
В сравнении с объявлением переменной разница мизерная: вместо двоеточия видим знак равенства, а вместо имени переменной – имя типа. Но каковы последствия! Объявите лишь однажды нужный вам тип, и тогда применяйте его, где угодно. Вот объявления типов для указанных выше переменных.
TYPE { примеры объявления типов-массивов }
{ тип для 30 строковых переменных с фамилиями учеников класса }
TNames = ARRAY [1..30] OF string;
{ тип для 30 байтовых переменных с оценками учеников }
TRatings = ARRAY [1..30] OF byte;
{ тип для 16 целых переменных с очками, набранными в чемпионате }
TChampionShip = ARRAY [1..16] OF integer;
Здесь буква «T» в имени типа напоминает о назначении этого идентификатора (помните наше добровольное соглашение об именах?). Теперь учрежденные типы данных можно употребить для объявления переменных и параметров в любом месте программы, вот пример.
TYPE { тип для 30 байтовых переменных с оценками учеников }
TRatings = ARRAY [1..30] OF byte;
VAR { 30 байтовых переменных с оценками учеников }
Ratings : TRatings;
procedure ABC (var arg: TRatings); { параметр процедуры }
var A, B, C : TRatings; { локальные переменные }
begin
...
end;
Здесь тип TRatings служит для объявления переменных и параметров в трех местах программы. В будущем мы всегда будем объявлять типы – как для массивов, так и для других сложных наборов данных.
Доступ к элементам (индексация)
Переменной-массивом можно ворочать как единым целым, например, при копировании одного массива в другой. Но чаще приходится работать с отдельными его элементами, как «выдернуть» их из массива?
Очень просто: воспользуйтесь индексацией, – она знакома вам по работе со строками. Как и для доступа к отдельному символу строки, для доступа к элементу массива надо указать его индекс, то есть порядковый номер в массиве. Индекс указывают в квадратных скобках, стоящих после имени массива, он представляет собой выражение порядкового типа. Кстати, сходство со строками не случайно, ведь строка – это особый род массива, составленного из отдельных символов.
Рассмотрим примеры доступа к элементам объявленных выше массивов.
Пример 1. Трем элементам массива Names присваиваем фамилии хоккеистов.
Names[1]:= ’Петров’;
Names[2]:= ’Михайлов’;
Names[3]:= ’Харламов’;
Пример 2. Сравниваем третий и четвертый элементы массива Ratings. Здесь индексы заданы через целочисленную переменную n.
…
Ratings[3]:= 12;
Ratings[4]:= 8;
n:=3;
if Ratings[n] > Ratings [n+1] then … else …;
Как видите, индекс в массиве можно вычислять, а это открывает дорогу к циклам. И мы двинемся ею немедленно!
Ввод и вывод массивов
Ввод и вывод – это те задачи, не решив которые, не стоит помышлять о применении массивов. Ни то, ни другое не сделать одним махом. Здесь, как и для множеств, нужны циклы, обрабатывающие отдельные элементы массива.
Взять, к примеру, массив Names, ввести который можно так: