Цикл while в языке Ада. Введение

Ранее мы уже познакомились с оператором loop, позволяющим организовать многократное повторение каких-либо действий:

loop
	[Действия]*
	exit when Условие_Выхода
	[Действия]
end loop;

* Квадратными скобками - [] - отмечены необязательные компоненты.

Сегодня мы познакомимся с ещё одним оператором цикла - while. Общий вид цикла while:

while Условие loop  --Пока выполняется условие,
	Действия        --Совершать заданные действия
end loop;

Цикл while будет повторять выполнение указанных действий до тех пор, пока будет выполняться условие, заданное после слова while. Причём, проверка условия будет происходить на каждой итерации (при каждом проходе). Это цикл с предусловием, т.е. возможна ситуация, когда while может не выполнится ни разу. Количество итераций цикла может быть заранее неизвестно и зависеть от конкретной задачи. Его можно использовать, например, при считывании файла:

<прочитать данные из файла>;           --символ, слово, строку и т.д.
while <не достигнут конец файла> loop
	<обработать элемент данных>;
	<прочитать следующий элемент данных>;
end loop;

Рассмотрим цикл while на примере решения задачи.

Задача: По данному целому числу N распечатайте все квадраты натуральных чисел, не превосходящие N, в порядке возрастания.

Формат входных данных:
Вводится натуральное число.
Формат выходных данных:
Выведите ответ на задачу.

Пример ввода:
50
Пример вывода:
1 4 9 16 25 36 49

with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
 
procedure main is
	N, i : Integer;
	--i - счётчик цикла
begin
	i := 1;                --начальная инициализация счётчика цикла
	Get(N);
	--Начало цикла
	while i * i <= N loop --Проверка условия (пока квадрат натурального числа меньше или равен N)
		Put(Item => (i * i), Width => 1);
		Put(" ");
		i := i + 1;        --увеличение счётчика цикла и переход к следующей итерации
	end loop;
	--Конец цикла
end main;

В приведённой выше задаче цикл while будет повторяться до тех пор, пока i * i не превысит значение N, а так как значение i на каждой итерации увеличивается на 1, то число повторений цикла не бесконечно.

Для прерывания цикла (выхода из цикла) также может использоваться оператор exit. Он позволяет выйти из цикла и перейти к следующей за циклом инструкции программы. Т.е. можно внутри цикла while организовать дополнительную проверку какого-то условия. Рассмотрим пример:

...
Sum := 0;
...
while Sum < 100 loop
	Get(A);         --Прочитать переменную A
	if A = 0 then   --Если А = 0, то
		exit;       --Выйти из цикла и продолжить выполнение программы с первой инструкции после цикла
	end if;
	Sum := Sum + A;
end loop;

Здесь выход из цикла произойдёт в двух случаях: если переменная Sum станет больше 100, или если пользователь введёт значение 0.

Также для выхода может использоваться уже рассмотренная ранее инструкция exit when

Можно организовать проверку сразу нескольких условий:

Sum := 0;
Get(A);
while Sum < 100 and A /= 0 loop   --Проверка сразу двух условий
	...
	Get(A);                       --Прочитать переменную A
	Sum := Sum + A;
end loop;

В приведённом примере на каждой итерации происходит проверка сразу двух условий. Если не будет выполнено хотя бы одно из них, цикл прервётся.

Как и в случае с условным оператором if, циклы могут быть вложены один в другой:

while Условие_1 loop
	[Действия_1]
	while Условие_2 loop
		[Действия_3]
		while Условие_N loop
			...
		end loop;
		[Действия_4]
	end loop;
	[Действия_2]
end loop;

Иногда возникают ситуации, когда нужно будет выйти из, например, самого внешнего цикла или из среднего. В этом случае можно использовать так называемые метки цикла. Метка устанавливается перед оператором цикла и имеет общий вид LABEL: Вместо слова "LABEL" можно использовать любое другое слово или букву.

Итак, с помощью оператора exit можно проходить сквозь несколько уровней вложенных один в другой циклов. Для этого используется конструкция exit L, где L - метка оператора цикла, выполнение которого нужно завершить. Рассмотрим пример:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
 
procedure Main is
	A, B, C : Integer;
begin
	A := 10;
	B := 10;
	C := 10;
 
--ВНЕШНИЙ ЦИКЛ
F:	while A /= 0 loop                             --F - метка оператора цикла (внешнего цикла)
		Put_Line("Сейчас выполняется внешний цикл.");
		Put("Введите 0 для выхода из внешнего цикла. A = "); Get(A);
		--СРЕДНИЙ ЦИКЛ
S:		while B /= -1 loop                        --S - метка оператора цикла (среднего цикла)
			Put_Line("Сейчас выполняется средний цикл.");
			Put("Введите -1 для выхода из среднего цикла. B = "); Get(B);
			--ВНУТРЕННИЙ ЦИКЛ
			while C /= -2 loop
				Put_Line("Сейчас выполняется внутренний цикл.");
				Put_Line("Введите -2 для выхода из внутреннего цикла (переход в средний цикл)");
				Put_Line("Введите -3 для выхода из среднего цикла (переход во внешний цикл)");
				Put_Line("Введите -4 для выхода из внешнего цикла (переход на первую инструкцию за внешним циклом)");
				Get(C);
				if C = -3 then     --Если C = -3, то
					exit S;        --выходим из среднего цикла (метка S)
				elsif C = -4 then  --Если C = -4, то
					exit F;        --выходим из внешнего цикла (метка F)
				end if;
			end loop;
			--КОНЕЦ ВНУТРЕННЕГО ЦИКЛА
			C := 10;       --Вернём C в исходный вид (чтобы можно было вновь войти во внутренний цикл)
		end loop S;
		--КОНЕЦ СРЕДНЕГО ЦИКЛА (С МЕТКОЙ S)
		B := 10;           --Вернём B в исходный вид (чтобы можно было вновь войти в средний цикл)
	end loop F;
--КОНЕЦ ВНЕШНЕГО ЦИКЛА (С МЕТКОЙ F)
	Put_Line("За пределами всех циклов.");
end Main;

Советую скомпилировать этот пример и "поиграть" с ним для более лучшего понимания материала.

Таким образом, возможны следующие формы оператора exit:

exit без уточнений, выход из самого внутреннего цикла, содержащего этот оператор
exit L выход из цикла, помеченного L
exit when condition выход из самого внутреннего цикла при выполнении условия condition
exit L when condition выход из цикла L при выполнении условия condition

Традиционно решим несколько задач по теме.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *