Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
62
Добавлен:
26.03.2016
Размер:
5.16 Mб
Скачать

Глава 39 Командная игра (массивы)

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 ...;

Как видите, индекс в массиве можно вычислять, а это открывает дорогу к циклам. И мы двинемся ею немедленно!

284

Глава 39 Командная игра (массивы)

Ввод и вывод массивов

Ввод и вывод — это те задачи, не решив которые, не стоит помышлять о применении массивов. Ни то, ни другое не сделать одним махом. Здесь, как и для множеств, нужны циклы, обрабатывающие отдельные элементы массива.

Взять, к примеру, массив Names, ввести который можно так:

for i:=1 to 30 do Readln(F, Names[i]);

Здесь F — это открытый для чтения текстовый файл, каждая строка которого содержит фамилию.

На первый взгляд всё просто. Просто, да не гладко, — это будет работать лишь с файлом, в котором не менее 30 строк (по числу циклов). А иначе случится ошибка: противозаконное чтение за пределами файла. Как избежать её? Внимательней присматривайте за концом файла, вот так:

i:=1;

{ пока не конец файла и не введены все элементы } while not Eof(F) and (i<=30) do begin

Readln(F, Names[i]); i:= i+1;

end;

А вот ещё один хороший вариант:

for i:=1 to 30 do begin

if Eof(F) then break; { если конец файла, прервать цикл } Readln(F, Names[i]);

end;

Вывод массива в файл не представляет труда, вот пример:

for i:=1 to 30 do Writeln(F, Names[i]);

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

Ошибки индексации

Объявление массива, как сказано, содержит границы для индексов: MIN — номер первого элемента, и MAX — номер последнего. А что случится при попытке обратиться к элементу с меньшим, чем MIN номером? Или наоборот — с большим, чем MAX? Иначе говоря, что случится при попытке доступа к несуществующему

285

Глава 39 Командная игра (массивы)

элементу массива? Такие ошибки преследуют даже опытных программистов, а последствия зависят от способа, которым вы совершите сей проступок.

Предположим, в программу вкрался такой оператор:

Names[200]:= ’Синичкин’;

Поскольку в массиве Names нет элемента с индексом 200, здесь вас остановит компилятор, — ошибка слишком явна, чтобы он промолчал. Вам не останется ничего иного, как исправить индекс, иначе программа не откомпилируется.

Но, когда индекс вычисляется при исполнении программы, нарушение границ проявляется и обрабатывается иначе, например:

Readln(N);

Writeln(Names[N]);

Нам не угадать, что введет пользователь в переменную N, — здесь ошибка нарушения границ может возникнуть при выполнении программы. В главе 27 мы рассматривали ошибки времени исполнения, — это как раз такой случай. Если указать индекс, выходящий за границы массива, то реакция программы будет зависеть от настройки компилятора, точнее, от опции контроля диапазонов. Напомню, что эта опция управляется директивой $R, а также доступна через меню по цепочке:

Options à Compiler… à Runtime Errors à Range checking

Рассмотрим вариант компиляции при включенном контроле границ ($R+). Тогда, при нарушении границ индекса, программа выдаст аварийное сообщение «Range check error». То есть, она заметила нарушение границ индекса, «крикнула» об этом и прервала работу.

Теперь отключим контроль диапазонов ($R-) и перекомпилируем программу. Она станет «легче» и быстрее, и по ходу выполнения проверять границы не станет. Но ошибки не пройдут бесследно. Наоборот, последствия будут тяжелыми и непредсказуемыми! Отключать проверку диапазонов позволительно только в тщательно проверенной программе.

Лучший способ избежать нарушения границ индексов — взять проверку на себя. В данном случае это можно сделать так:

286

Глава 39 Командная игра (массивы)

repeat

Readln(N);

if N in [1..30]

then Writeln(Names[N])

else Writeln(’Ошибка! Введите индекс от 1 до 30’);

until N in [1..30]

Этот цикл будет терзать пользователя, пока тот не введет допустимое значение индекса, или не выключит компьютер.

Итоги

Массив – это сложный тип данных, объединяющий в себе несколько однотипных переменных – элементов массива.

Все элементы массива носят одно общее имя – это имя самого массива. Внутри массива элементы различаются своими порядковыми номерами –

индексами.

В объявлении массива указывают две его характеристики: диапазон индексов и тип элементов.

Индекс элемента может быть задан числом или выражением порядкового типа.

Указание неверного индекса порождает ошибки либо при компиляции, либо при выполнении программы.

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

Аслабо?

А) Массив A и переменная C объявлены так:

var A : array [’a’..’z’] of integer;

C: char;

Допустимо ли такое объявление массива и почему? Сколько элементов содержит массив? Какие из указанных ниже операторов будут (или могут) вызывать ошибки нарушения диапазонов?

A[’s’]:= 10;

A[’R’]:= 10;

C:=’d’;

A[C]:= 10;

Readln(C); A[C]:= 10;

Проверьте свои решения на практике.

287

Соседние файлы в папке delphi