Операторы ветвления: if и case. Массивы: описание и использование. Операторы цикла: for, while и repeat. Прерывание циклов: break, continue и goto.
Содержание
Операторы ветвления
К операторам, позволяющим из нескольких возможных вариантов выполнения программы (ветвей) выбрать только один, относятся if и case.
Условный оператор if
Оператор if выбирает между двумя вариантами развития событий:
if <условие> then <один_оператор> [else <один_оператор>];
Обратите внимание, что перед словом else (когда оно присутствует, конечно же) символ «;» не ставится — ведь это разорвало бы оператор на две части.
Условный оператор if работает следующим образом:
- Сначала вычисляется значение <условия> — это может быть любое выражение, возвращающее значение типа Boolean.
- Затем, если в результате получена «истина» (True), то выполняется оператор, стоящий после ключевого слова then, а если «ложь» (False) — без дополнительных проверок выполняется оператор, стоящий после ключевого слова else. Если же else–ветвь отсутствует, то не выполняется ничего.
Что же произойдёт, если написать несколько вложенных операторов if?
В случае, когда каждый оператор if имеет собственную else–ветвь, всё будет в порядке. А вот если некоторые из них этой ветви не имеют, может возникнуть ошибка. Компилятор языка Pascal всегда считает, что else относится к самому ближнему оператору if. Таким образом, если написать
if s > 2 then
s := 1
else
s := -1;
подразумевая, что else–ветвь относится к внешнему оператору if, то компилятор всё равно воспримет эту запись как
if s > 2 then
s := 1
else s := -1;
Ясно, что таким образом правильного результата получить не удастся.
Для того чтобы избежать подобных ошибок, стоит всегда (или, по крайней мере, при наличии нескольких вложенных условных операторов) вкладывать внутренние операторы в блок begin .. end. Так вы застрахуетесь от одной из частых «ошибок по невнимательности», которые очень сложно найти в процессе отладки программы.
Итак, исходный вариант нужно переписать следующим образом:
begin
if s > 2 then
s := 1;
end
else
s := -1;
Вообще же, если есть возможность переписать несколько вложенных условных операторов как один оператор выбора, это стоит сделать.
Оператор выбора case
Оператор case позволяет сделать выбор между несколькими вариантами:
case <переключатель> of <список_констант> : <один_оператор>; [<список_констант> : <один_оператор>;] [<список_констант> : <один_оператор>;] [else <один_оператор>;] end;
Замечание: Обратите внимание, что после else двоеточие не ставится.
Существуют дополнительные правила, относящиеся к структуре этого оператора:
- Переключатель должен относиться только к порядковому типу данных, но не к типу LongInt.
- Переключатель может быть переменной или выражением.
- Список констант может задаваться как явным перечислением, так и интервалом или их объединением.
- Повторение констант не допускается.
- Тип переключателя и типы всех констант должны быть совместимыми1.
Пример оператора выбора:
'a' .. 'z', 'A' .. 'Z' : WriteLn('Это латинская буква');
'а' .. 'я', 'А' .. 'Я' : WriteLn('Это русская буква');
'0' .. '9' : WriteLn('Это цифра');
' ', #10, #13, #26 : WriteLn('Это пробельный символ');
else WriteLn('Это служебный символ');
end;
Выполнение оператора case происходит следующим образом:
- вычисляется значение переключателя;
- полученный результат проверяется на принадлежность к тому или иному списку констант;
- если такой список найден, то дальнейшие проверки уже не производятся, а выполняется оператор, соответствующий выбранной ветви, после чего управление передаётся оператору, следующему за ключевым словом end, которое закрывает всю конструкцию case.
- если подходящего списка констант нет, то выполняется оператор, стоящий за ключевым словом else. Если else–ветви нет, то не выполняется ничего.
Иллюстрация if и case
В качестве примера, иллюстрирующего использование операторов ветвления, приведём несколько различных реализаций функции Sgn(x)2 — знак числа х. Из математики известно, что эта функция имеет следующие значения:
Sgn(x) = -1, если x < 0; Sgn(x) = 0, если x = 0; Sgn(x) = 1, если x > 0.
Реализовать эту функцию для случая, когда х вещественное, можно следующими способами (при условии, что x : Real; Sgn : -1 .. 1;):
- Это так называемая реализация «в лоб». Здесь нет никаких хитростей и никаких попыток оптимизации: даже, если сработает первый вариант, второй и третий всё равно будут проверены, невзирая на то, что результат уже получен.if x = 0 then Sgn := 0;
if x < 0 then Sgn := -1;
if x > 0 then Sgn := 1; - Этот вариант свободен от излишних проверок в случае, если значение переменной не положительно. Эту реализацию следует признать более эффективной, чем предыдущаяif x = 0 then
sgn := 0
else if x < 0 then
sgn := -1
else
sgn := 1; - Ещё одна попытка сократить текст программы. Здесь используется стандартная функция Abs(), которая возвращает абсолютное значение аргумента. Проблема в данном случае состоит в том, что «/» — деление дробное, но ведь нам необходим целый, а не вещественный ответ! «Давайте воспользуемся стандартной функцией округления», — скорее всего, скажет внимательный читатель.if x = 0 then
Sgn := 0
else
Sgn := x / Abs(x); - И, действительно, исправленный вариант будет выдавать верный результат.if x = 0 then
Sgn := 0
else
Sgn := Round(x / Abs(x)); - А вот ещё один (правда, несколько неестественный) способ с использованием оператора выбора. Вся хитрость этого варианта в том, что выбирающий ветви переключатель обязан принадлежать к перечислимому типу, именно поэтому пришлось заменить «х» на «х = 0». Напомним, что эта операция сравнения выдаёт результат логического типа Boolean, и именно логические константы True и False фигурируют в качестве меток выбора.case x = 0 of
True: Sgn := 0;
False: Sgn := Round(x / Abs(x));
end;
Конечно же, мы перебрали далеко не все возможные способы реализации функции Sgn(x) (ведь сколько людей, столько и способов выражать свои мысли — хоть в литературе, хоть в программировании). Однако уже на этом простеньком примере видно, что способов запрограммировать желаемое всегда больше, чем один, и вряд ли самое простое решение будет и оптимальным.