Пример кода оператора цикла Паскаля с постусловием
Readln(n);
i:=0;
y:=0;
Repeat
i:=i+1;
y:=y+1/i;
Until i>n;
Оператор цикла Паскаля с предусловием
В случае оператора цикла Паскаля с постусловием входящая в него последовательность операторов заведомо будет выполняться хотя бы один раз. Между тем довольно часто встречаются такие циклические процессы, когда число повторений цикла тоже неизвестно заранее, но при некоторых значениях исходных данных предусмотренные в цикле действия вообще не должны выполняться, и даже однократное выполнение этих действий может привести к неверным или неопределенным результатам.
Пусть, например, дано вещественное число М. Требуется найти наименьшее целое неотрицательное число k, при котором 3 k> M. Эту задачу можно решить по следующему алгоритму: предварительно положить y=1 и k=0; затем в цикле домножать значение y на 3 и увеличивать значение k на 1 до тех пор, пока текущее значение y впервые окажется больше значения М. На первый взгляд, здесь можно воспользоваться оператором цикла с постусловием:
Пример кода оператора цикла Паскаля с постусловием
y:=1; k:=0;
Repeat
y:=y*3;
k:=k+1;
Until y> M;
Однако нетрудно убедиться в том, что при M<1 будет получен неправильный результат k=1, тогда как должно быть получено k=0: в этом случае предварительно сформированное значение k=0 является окончательным результатом и действия, предусмотренные в цикле, выполняться не должны.
Для задания подобного рода вычислительных процессов, когда число повторений цикла заранее неизвестно и действия, предусмотренные в цикле, могут вообще не выполняться, и служит оператор цикла с предусловием. Этот оператор цикла имеет в Паскале следующий вид:
While B do S,
где while (пока), do (делать, выполнять) – служебные слова, В – логическое выражение, S – оператор. Здесь оператор S выполняется ноль или более раз, но перед каждым очередным его выполнением вычисляется значение выражения В, и оператор S выполняется только в том случае, когда значение выражения В true. Выполнение оператора цикла завершается, когда выражение В впервые принимает значение false. Если это значение выражение В принимает при первом же его вычислении, то оператор S не выполнится ни разу.
В рассматриваемой нами задаче правильное значение k при любом значении М может быть получено следующим образом:
Пример кода оператора цикла Паскаля с предусловием
y:=1; k:=0;
While y<=M do
Begin
y:=y*3;
k:=k+1;
End;
Оператор цикла Паскаля с предусловием можно считать наиболее универсальным – с использованием таких операторов можно задать и циклические процессы, определяемые операторами цикла с параметром и постусловием.
Отметим отличия и особенности хорошего стиля работы с рассмотренными циклическими операторами.
Цикл с предусловием While (пока условие истинно) | Цикл с постусловием Repeat (до истинности условия) |
1. До начала цикла должны быть сделаны начальные установки переменных, управляющих условием цикла, для корректного входа в цикл | |
2. В теле цикла должны присутствовать операторы, изменяющие переменные условия так, чтобы цикл через некоторое число итераций завершился | |
3. Цикл работает пока условие истинно (пока True) | 3. Цикл работает пока условие ложно (пока False) |
4. Цикл завершается, когда условие становится ложным (до False) | 4. Цикл завершается, когда условие становится истинным (до True) |
5. Цикл может не выполниться ни разу, если исходное значение условия при входе в цикл False | 5. Цикл обязательно выполнится как минимум один раз |
6. Если в теле цикла требуется выполнить более одного оператора, то необходимо использовать составной оператор | 6. Независимо от количества операторов в теле цикла, использование составного оператора не требуется |
Цикл со счетчиком (с параметром) For | |
· Начальная установка переменной счетчика цикла до заголовка не требуется | |
· Изменение в теле цикла значений переменных, стоящих в заголовке не допускается | |
· Количество итераций цикла неизменно и точно определяется значениями нижней и верхней границ и шага приращения | |
· Нормальный ход работы цикла может быть нарушен оператором goto или процедурами Break и Continue | |
· Цикл может не выполниться ни разу, если шаг цикла будет изменять значение счетчика от нижней границы в направлении, противоположном верхней границе |
Оператор, который выполняется в цикле, сам может быть циклом. Это относится ко всем видам циклов. В результате мы получаем вложенные циклы. Механизм работы вложенных циклов удобнее всего рассмотреть на примере вложенных циклов с параметром. Пусть нам нужно описать работу электронных часов, начиная с момента времени 0 часов, 0 минут, 0 секунд. Значение минут станет равным 1 только после того, как секунды «пробегут» все последовательные значения от 0 до 59. Часы изменят свое значение на 1 только после того, как минуты «пробегут» все последовательные значения от 0 до 59. Таким образом, вывод всех значений времени от начала суток до конца суток может быть представлен следующим фрагментом программы:
For h:=0 to 23 do
For m:=0 to 59 do
For s:=0 to 59 do
Writeln(h,’:’,m,’:’,s);
Для удобства реализации циклических структур на Паскале в последних версиях языка введены операторы break и continue, применяемые внутри циклов. Они расширяют возможности использования циклов и улучшают структуру программы.
В процессе выполнения тела цикла до полного завершения цикла могут возникнуть дополнительные условия, требующие завершения цикла. В этом случае цикл может быть прекращен оператором break.
В ходе выполнения цикла может возникнуть условие, при котором необходимо пропустить все или некоторые действия, предусмотренные в цикле, не прекращая работу цикла совсем. Для этого используется оператор continue, который передает управление в ту точку программы, где проверяется условие продолжения или прекращения цикла.
Циклический вычислительный процесс (ЦВП) характеризуется повторением одних и тех же вычислений над некоторым набором данных. Числом повторений цикла управляет специальная переменная, называемая его счетчиком или управляющей переменной цикла. На счетчик накладывается условие, определяющее, до каких пор следует выполнять цикл.
Повторяемый блок вычислений называют телом цикла. В теле цикла должно быть обеспечено изменение значения счетчика, чтобы он мог завершиться. Если тело цикла состоит более чем из одного оператора, оно заключается в операторные скобки begin... end;. Однократное выполнение тела цикла называют его шагом.
Таким образом, для программирования цикла достаточно определить условие, управляющее числом его повторений и описать операторы, образующие тело цикла. С этой точки зрения, теоретически возможны всего два вида циклов -- проверка условия либо предшествует выполнению тела цикла, либо происходит после него. Изобразим эти циклы в виде блок-схем (рис. 9.1).
В цикле с предусловием сначала проверяется условие, затем, в зависимости от того, истинно оно или ложно, либо выполняется тело цикла, либо следует переход к оператору, следующему за телом цикла. После завершения тела цикла управление вновь передается на проверку условия. Естественно, предполагается, что в теле цикла было обеспечено некоторое изменение входящих в условие переменных -- в противном случае произойдет зацикливание и программа "зависнет".
Рис. 9.1. Блок-схемы циклов с предусловием и постусловием
Для цикла с постусловием сначала выполняется тело цикла, затем управление передается на проверку условия. В зависимости от истинности или ложности условия, тело цикла выполняется повторно или же происходит переход к оператору, следующему за телом цикла. Всё, сказанное о возможном зацикливании для цикла с предусловием, справедливо и для цикла с постусловием.
Исходя из приведенных блок-схем, очевидно основное различие двух циклов: цикл с постусловием гарантированно выполняется хотя бы раз, а цикл с предусловием может не выполняться ни разу, если условие сразу же окажется ложным.
В языке Паскаль реализованы оба вида циклов. Цикл с предусловием имеет следующий общий вид:
while логическое_выражение do begin
{операторы тела цикла}
end;
Работу цикла можно описать словами: "пока логическое выражение истинно, повторяется тело цикла".
Логическое выражение строится по правилам, изученным в гл. 7. Тело цикла могут образовывать любые операторы Паскаля. Если в цикле находится всего один оператор, операторные скобки, показывающие начало и конец тела цикла, можно не писать.
Общая запись цикла с постусловием следующая:
repeat
{операторы тела цикла}
until логическое_выражение;
Работает цикл с постусловием следующим образом: "тело цикла повторяется до тех пор, пока логическое выражение не станет истинным". Обратите внимание, что, в отличие от while, цикл repeat в Паскале работает, пока условие ложно. Это отличие подчеркивается использованием ключевого слова until ("до тех пор, пока не") вместо while ("до тех пор, пока"). Кроме того, в виде исключения, тело цикла repeat, даже если оно состоит из нескольких операторов, можно не заключать в операторные скобки.
Довольно часто циклы взаимозаменяемы. Представим, например, что для каждого из значений переменной x=1, 2,...,20, нужно выполнить некоторый расчет (математически этот закон изменения x можно записать как или ). Это можно сделать как в цикле while:
x:=1;
while x<=20 do begin
{операторы расчета}
x:=x+1;
end;
так и с помощью repeat:
x:=1;
repeat
{операторы расчета}
x:=x+1;
until x>20;
Как видно из листинга, управляющей переменной x в обоих случаях присвоено начальное значение 1, оба цикла изменяют значение x и, соответственно, условие цикла, оператором x:=x+1;, но для цикла repeat условие "перевернуто" ("пока x не станет больше 20"), а тело не заключено в операторные скобки.
Зачастую использование одного из циклов выглядит предпочтительней. Например, обработка ввода пользователя с клавиатуры удобней с помощью repeat (сначала пользователь должен нажать клавишу, затем следуют проверки и обработка).