6.6. Оператор цикла с параметром (FOR...DO)
Операторы циклов с пред- и с постусловием, хотя и обладают значительной гибкостью, не слишком удобны для организации
- 101 -
«строгих» циклов, которые должны быть проделаны данное число раз. Цикл с параметром вводится именно для таких случаев. Синтаксис оформления циклов с параметром следующий:
FOR ПараметрЦикла:=МладшееЗнач TO СтаршееЗнач DO Оператор;
или
FOR ПараметрЦикла := СтаршееЗнач DOWNTO МладшееЗнач DO
Оператор;
Слова FOR...TO (DOWNTO)...DO можно перевести как «для параметра от...до...делать».
Оператор, представляющий собой тело цикла, может быть простым, составным или пустым. В последнем случае за словом DO сразу ставится точка с запятой. Параметр цикла, а также диапазон его изменения (от стартового до конечного значения включительно) может быть только целочисленного или перечислимого типа. Сам параметр должен быть описан совместно с прочими переменными. Шаг цикла FOR всегда постоянный и равен «интервалу» между двумя ближайшими значениями типа параметра цикла. Изменение параметра цикла может быть возрастающим, но может быть и убывающим. В первом случае МладшееЗначение должно быть не больше чем Старшее, а во втором — наоборот. Примеры оформления циклов с параметром приведены на рис. 6.2.
| VAR
| i : Integer; { описание параметров циклов}
| c : Char;
| b : Boolean;
| e : (elem1, elem2, elem3 ); {вводимый перечислимый тип}
| BEGIN
| FOR i:= -10 TO 10 DO Writeln(i);
| FOR i:= 10 DOWNTO -10 DO Writeln(i);
| FOR c:= 'a' TO 'r' DO Writeln(с);
| FOR b:=True DOWNTO False DO Writeln(b);
| FOR e:= elem1 TO elem3 DO Writeln(Ord(e));
| END.
Рис. 6.2
Если параметр возрастает, то между границами его значений ставится слово TO, если же убывает, то ставится слово DOWNTO. Соответственно с этим меняются местами старшее и младшее зна-
- 102 -
чения в заголовке цикла. На месте старших и младших значений могут стоять константы (как на рис. 6.2), а могут и переменные или выражения, совместимые по присваиванию с параметром цикла. Выполнение цикла начинается с присваивания параметру стартового значения. Затем следует проверка, не превосходит ли параметр конечное значение (случай с TO) или не является ли он меньше конечного значения (случай с DOWNTO). Если результат проверки утвердительный, то цикл считается завершенным и управление передается следующему за телом цикла оператору. В противном случае выполняется тело цикла, и после этого параметр меняет свое значение на следующее, согласно заголовку цикла. Далее снова производится проверка значения параметра цикла, т.е. алгоритм повторяется. Из этого следует, что будут проигнорированы циклы
FOR i := 5 ТО 4 DO ...;
FOR i : = 4 DOWNTO 5 DO ...;
а цикл
FOR i := N TO N DO ...;
выполнит операторы своего тела строго один раз.
Запрещается изменять параметр цикла и его старшее и младшее значения (если они заданы переменными или выражениями с ними) изнутри тела цикла. Кроме того, параметр цикла не может участвовать в построении диапазонов этого же цикла. Компилятор таких «незаконных» действий не замечает, но программа, содержащая цикл с заголовком типа
FOR i := i-5 TO i+5 DO ...
не заслуживает никакого доверия, даже если запускается. Если же необходимо досрочно завершить цикл FOR (для чего велик соблазн искусственно «подрастить» параметр цикла), то можно воспользоваться оператором перехода Goto (о нем см. следующий раздел). В техническом описании Турбо Паскаля отмечается, что после завершения цикла FOR значение его параметра не определено. При экспериментальной проверке этого факта скорее всего получится обратный результат: параметр будет иметь конечное значение своего диапазона. Тем не менее, не следует опираться на это в своих программах. Лучше переприсвоить значение параметра после окончания цикла — так будет корректнее. Исключение — выход из цикла переходом Goto. В этом случае значение переменной (параметра цикла) останется таким же, каким было на момент выполнения оператора Goto.
- 103 -
Циклы с параметром — очень быстрые и генерируют компактный выполнимый код. Но всем им присущ один традиционный в Паскале недостаток — параметр должен принадлежать к перечислимому типу, а шаг не может быть изменен. Так, в первых двух циклах на рис. 6.2 шагом будет значение +1 и -1 соответственно, в цикле от 'а' до 'г' параметр C примет последовательные значения 'а', 'б', 'в', 'г', т.е. каждый следующий элемент — это значение функции Succ(C). Следствием этого являются проблемы организации циклов с шагом, отличным, например, от 1, а тем более циклов с вещественным параметром.
Для разрешения таких проблем приходится использовать обходные пути: обращаться к циклам с условиями. Так, цикл с вещественным параметром r от 3,20 до 4,10 с шагом 0,05 можно запрограммировать циклом WHILE:
r:=3.20;
WHILE r<=4.10 do
BEGIN
...
r := r + 0.05
end;
Возвращаясь к циклам FOR, заметим, что они допускают вложенность при условии, что никакой из вложенных циклов, наряду с другими операторами, не использует и не модифицирует переменные — параметры внешних циклов.