Операторы цикла используются для повторения (итераций) одного или нескольких операторов определенное количество раз.
Оператор_цикла::= оператор_for | оператор_while | оператор_repeat
Цикл For
Цикл For используется для повторения оператора фиксированное количество раз.
оператор_for::=
"for" управляющая_переменная ":=" начальное_значение
("to" | "downto") конечное_значение "do" оператор.
Где управляющая переменная - идентификатор порядковой переменной, начальное и конечное значения - выражения порядкового типа (см. параграф 1.7.1.1).
Управляющая переменная должна быть объявлена в том же блоке, где используется оператор цикла (например, если цикл используется внутри процедуры, управляющая переменная также должна быть определена внутри этой процедуры).
При входе в цикл начальное и конечное значения фиксируются и остаются постоянными во время выполнения цикла. Управляющая переменная инициализируется начальным значением. После окончания выполнения оператора в теле цикла производится сравнение управляющей переменной с конечным значением. Если они оказываются равны, то происходит выход из цикла, иначе – либо увеличение("to"), либо уменьшение ("downto") управляющей переменной на 1 и переход на новую итерацию цикла.
Если при входе в цикл начальное значение больше ("to"), либо меньше ("downto") конечного значения, то происходит немедленный выход из цикла без выполнения его тела.
Примеры использования цикла FOR:
Задача 8. Вывести на экран первые N натуральных чисел.
Решение:
var n,i:integer;
begin
readln;
for i:=1 to n do writeln(i);
readln;
end.
Задача 9. Вывести на экран первые N положительных четных чисел в обратном порядке.
Решение:
var n,i:integer;
begin
readln;
for i:=n downto 1 do writeln(i*2);
readln;
end.
Задача 10. Подсчитать сумму и произведение последовательности натуральных чисел из промежутка [N,M].
Рассмотрим подробно решение задачи :
var n,m,i:integer;
s,p:real;
begin
readln(n,m);
s:=0; p:=1; {присваиваем первоначальное значение переменным,
отвечающим за сумму и произведение }
for i:=n to m do begin { открываем цикл для перебора всех
натуральных значений от N до М }
s:=s+i; p:=p*i; {увеличиваем текущее значение суммы на I,
а текущее значение произведения в I раз}
end; { Завершаем тело цикла. При этом значение переменной I
увеличивается на единицу и сравнивается с М. Если I>M,
то происходит выход из цикла, иначе выполнение
программы переходит на начало тела цикла }
writeln('Сумма = ',s);
writeln('Произведение = ',p);
readln;
end.
Задача 11. Вычислить сумму из N слагаемых:
Решение:
Для решения задачи целесообразно вывести общую формулу:
var i,n:integer;
s:real;
begin
readln;
s:=0;
for i:=1 to n do s:=s+1/i;
writeln(s);
readln;
end.
Задача 12. Вывести на экран таблицу умножения.
Решение:
Для решения данной задачи нам потребуется воспользоваться понятием "вложенного цикла", которое подразумевает использование одного цикла внутри другого.
var i,k:integer;
begin
for i:=1 to 10 do begin {открываем внешний цикл, с помощью которого осуществляем перебор всех десяти строк}
for k:=1 to 10 do write(i*k:4); {во внутреннем цикле для каждой строки осуществляем перебор всех столбцов и выводим на экран произведение номера столбца и строки. Для выравнивания используем специальный синтаксис оператора write (см. описание вывода числовых выражений в параграфе 1.1)}
writeln; {после завершения внутреннего цикла производим переход на следующую строку }
end;
readln;
end.
При использовании цикла FOR следует придерживаться следующих правил:
1) Не присваивать какое-либо значение управляющей переменной внутри цикла. В результате такого действия могут возникнуть следующие ситуации:
а) Незапланированный выход из цикла (что гораздо проще организовать с помощью процедуры break)
б) "Зацикливание" - бесконечное выполнение тела цикла, и как результат - "зависание" программы.
в) Неверное количество итераций цикла.
Ниже приводится пример, иллюстрирующий типичную ошибку, связанную с непониманием функционирования цикла FOR.
Задача 13. Вывести на экран первые N нечетных чисел.
Решение:
Var i,n:intеger;
Begin
Readln;
For i:=1 to n do begin
Writeln(i);
i:=i+2; {НЕВЕРНО! Нельзя рассчитывать получить из единицы тройку, из тройки - пятерку и т.д. таким методом внутри цикла FOR. Управляющая переменная I сама увеличивается на единицу при каждой итерации, что учетом ее изменения в данном операторе даст приращение на 3}
End;
Readln;
End.
Результат работы этой программы зависит от введенного числа N. Если конечное значение не кратно 3, то произойдет "зависание", так как увеличивающееся значение управляющей переменной никогда не станет равно конечному значению (естественно, рассматривая идеальный случай, когда множество натуральных чисел бесконечно, что для типа integer конечно же не так. На самом деле, выполнение цикла закончится, сделав 2-3 круга по всему типу integer, что займет значительный объем времени и бессмысленных вычислений). Если введенное значение окажется кратным 3, то выход из цикла произойдет вовремя, оставив на экране, к сожалению, отнюдь не последовательность нечетных чисел.
С помощью элементарных арифметических действий легко получить более короткое и, что самое главное, верное решение задачи:
var n,i:integer;
begin
readln;
for i:=1 to n do writeln(i*2-1);
Readln;
end.
2) Не изменять начальных и конечных значений управляющей переменной, рассчитывая при этом на изменение количества итераций цикла (данное ограничение имеет смысл только при использовании переменных в качестве конечных или начальных значений).
Задача 14. Дано натуральное число N. Вывести на экран все натуральные числа из промежутка [1,N+X], где X - количество таких чисел из промежутка [1,N], которые кратны 3 и не кратны 5.
Типичный подход в решении такой задачи с использованием только цикла FOR состоит в подсчете в первом цикле количества чисел по правилу, определенному в условии задачи, и выводе требуемого количества чисел на экран во втором цикле. Попытки сократить программу могут привести к следующему, в корне неверному с точки зрения семантики языка, решению:
Var i,n:intеger;
Begin
Readln;
For i:=1 to n do begin
Writeln(i);
If (i mod 3=0)and(i mod 5<>0) then n:=n+1; {НЕВЕРНО!}
End;
Readln;
End.
Увеличение значения переменной N внутри цикла не каким образом не повлияет на количество итераций.
Для решения данной задачи только с помощью цикла FOR нам потребуется несколько увеличить объем программы:
Var i,n:intеger;
Begin
Readln;
For i:=1 to n do begin
If (i mod 3=0)and(i mod 5<>0) then n:=n+1;
End; {воспользовавшись спецификой цикла FOR, нашли требуемую верхнюю границу промежутка, не вводя при этом дополнительных переменных}
for i:=1 to n do writeln(i); {вывели на экран все натуральные числа из определенного в условии промежутка}
Readln;
End.
Цикл While
Цикл While или, как его еще называют, цикл с предусловием, используется для условного повторения оператора, который называют телом цикла.
оператор_While::=
"while" логическое_выражение "do" оператор.
При входе в цикл проверяется логическое выражение. Пока его значение равно True, оператора тела цикла повторяются.
Задача 15. Вычислить бесконечную сумму с точностью до одной сотой:
Решение:
Для решения задачи нет возможности воспользоваться циклом for, так как заранее неизвестно количество членов последовательности, сумма которых вычисляется. Поэтому используем в программе цикл while:
var i,n:integer;
s,p:real;
Const Tochnost=0.01;
begin
s:=0; i:=1;
p:=1/(i*i*i); {Переменной p требуется присвоить первоначальное значение перед входом в цикл. Иначе при первом входе логическое выражение может быть рассчитано неверно }
while p>= Tochnost do begin
s:=s+p;
i:=i+1;
p:= 1/(i*i*i);
end;
writeln(s);
readln;
end.
Задача 16. Попробуем увеличить скорость получения последовательности натуральных чисел при решении задачи №14. Напоминаем ее условие:
Дано натуральное число N. Вывести на экран все натуральные числа из промежутка [1,N+X], где X - количество таких чисел из промежутка [1,N], которые кратны 3 и не кратны 5.
Как было показано выше, используя цикл FOR, мы не можем обойтись только одним циклом, так как во время выполнения его тела ТП не допускает изменения конечного количества итераций. Цикл WHILE более либерален в этом отношении.
Var i,n:integer;
Begin
Readln;
i:=1;
While i<=n do begin
If (i mod 3=0)and(i mod 5<>0) then n:=n+1;
Writeln(i);
i:=i+1;
End;
Readln;
End;
Цикл Repeat
Цикл Repeat или, как его еще называют, цикл с постусловием, также, как и цикл while, используется для условного выполнения операторов, находящихся в теле цикла. Его отличительной особенностью является то, что проверка условия выхода из цикла происходит после выполнения тела цикла.
оператор_Repeat::=
"repeat" оператор {";" оператор } [";"]
"until" логическое_выражение.
Повторение оператора заканчивается (то есть происходит выход из цикла), когда логическое выражение принимает значение True.
Задача 17. Рассмотрим задачу №15, приведенную для иллюстрации возможностей цикла while. Напомним ее условие: Вычислить бесконечную сумму с точностью до одной сотой:
var i,n:integer;
s,p:real;
Const Tochnost=0.01;
begin
s:=0; i:=1;
{ в отличие от цикла while первоначальное
значение промежуточного произведения
не требуется рассчитывать до тела цикла,
так как проверка условия производится не
в начале, а в конце цикла.}
repeat
p:= 1/(i*i*i);
s:=s+p;
i:=i+1;
until p<Tochnost;
{ Выход из цикла произошел, когда в искомой сумме уже было учтено последнее слагаемое, значение которого меньше, чем требуемая погрешность. }
writeln(s-p); { Поэтому исключаем данный член последовательности из суммы}
readln;
end.