Циклы while и repeat, вложенность и досрочный выход

Урок разбирает циклы while и repeat, которые повторяют действия по условию, вложенные циклы и способы досрочно выйти из цикла.

while повторяет тело, пока условие истинно; repeat...until повторяет тело, пока условие не станет истинным.

Когда число повторов заранее неизвестно

Цикл for хорош, когда мы точно знаем, сколько раз повторить. Но часто это неизвестно. «Повторяй, пока пользователь не введёт правильный пароль». «Дели число пополам, пока оно больше единицы». «Считай цифры числа, пока оно не обнулится». Здесь количество шагов зависит от данных. Для таких задач нужны циклы, управляемые условием, а не счётчиком: while и repeat.

Цикл while: проверка в начале

Цикл while («пока») проверяет условие перед каждым повторением. Пока условие истинно — тело выполняется; как только стало ложным — цикл завершается:

var
  n: integer;
begin
  n := 100;
  while n > 1 do
  begin
    write(n, ' ');
    n := n div 2;     // уменьшаем n, иначе зациклимся
  end;
  writeln;
end.

Эта программа делит 100 пополам, пока число больше 1: 100, 50, 25, 12, 6, 3, 1. Ключевой момент — внутри тела мы обязательно меняем переменную n, от которой зависит условие. Если этого не делать, условие навсегда останется истинным, и программа зациклится — будет крутиться вечно. Это самая опасная ошибка с while. Запустите аналог:

n = 100
while n > 1:
    print(n, end=' ')
    n = n // 2
print()

Вывод:

100 50 25 12 6 3 

Важная особенность while: если условие ложно с самого начала, тело не выполнится ни разу. Проверка стоит в начале — это цикл «с предусловием».

Цикл repeat: проверка в конце

Цикл repeat...until («повторять... пока не») устроен наоборот: тело выполняется сначала, а условие проверяется в конце. Поэтому тело гарантированно выполнится хотя бы один раз. И ещё отличие: repeat повторяется, пока условие ложно, и останавливается, когда оно становится истинным (until = «до тех пор, пока не»).

var
  password: integer;
begin
  repeat
    write('Введите код (нужен 42): ');
    readln(password);
  until password = 42;
  writeln('Доступ разрешён!');
end.

Этот цикл будет спрашивать код снова и снова, пока пользователь не введёт 42. Идеально для проверки ввода: спросить хотя бы раз, а повторять при ошибке. Приятный бонус: repeat...until сам по себе ограничивает блок команд, поэтому begin...end внутри не нужны.

Признакwhilerepeat
Где проверка условияв началев конце
Повторяется, пока условие...истинноложно
Минимум выполнений тела0 раз1 раз
Нужны begin/endда (для нескольких команд)нет

Разбор числа на цифры

Классическая задача на while — посчитать сумму цифр числа, когда мы не знаем, сколько в нём цифр. Используем приёмы из урока про div и mod: mod 10 даёт последнюю цифру, div 10 убирает её. Повторяем, пока число не обнулится:

n = 4926
sum = 0
while n > 0:
    sum = sum + n % 10   # прибавляем последнюю цифру
    n = n // 10          # убираем последнюю цифру
print('Сумма цифр:', sum)

Вывод:

Сумма цифр: 21

Здесь for не подошёл бы — мы заранее не знаем число цифр. А while отлично справляется: крутится ровно столько раз, сколько цифр в числе.

Вложенные циклы

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

for i in range(1, 4):
    for j in range(1, 4):
        print(i, '*', j, '=', i * j, end='   ')
    print()   # перенос строки после каждой строки таблицы

Вывод:

1 * 1 = 1   1 * 2 = 2   1 * 3 = 3   
2 * 1 = 2   2 * 2 = 4   2 * 3 = 6   
3 * 1 = 3   3 * 2 = 6   3 * 3 = 9   

На Паскале это выглядело бы так: внешний for i := 1 to 3, а внутри него — for j := 1 to 3 со своим телом. У каждого цикла своя переменная-счётчик (i и j). Вложенные циклы — основа работы с таблицами и матрицами, которые мы изучим в следующем разделе.

Досрочный выход: break и continue

Иногда нужно прервать цикл раньше, не дожидаясь его естественного конца. Например, ищем элемент и нашли — зачем продолжать? Для этого есть две команды:

  • break — немедленно выйти из цикла полностью.
  • continue — пропустить остаток текущего шага и перейти к следующему повтору.
for i in range(1, 11):
    if i == 5:
        print('Нашли пятёрку, выходим')
        break
    print('Проверяю', i)

Вывод:

Проверяю 1
Проверяю 2
Проверяю 3
Проверяю 4
Нашли пятёрку, выходим

В Паскале эти команды называются так же: break и continue. Пользуйтесь ими аккуратно: они удобны, но избыток досрочных выходов делает логику цикла запутанной. Часто более ясно подобрать правильное условие в while.

Попробуй сам

Напишите программу, которая находит наименьший делитель числа (кроме 1). Перебирайте делители d от 2 и проверяйте n mod d = 0; как только нашли — выводите и выходите через break. Проверьте на Python для числа 91:

n = 91
d = 2
while d <= n:
    if n % d == 0:
        print('Наименьший делитель:', d)
        break
    d = d + 1

Вывод:

Наименьший делитель: 7

Частые ошибки

  • Зацикливание. Если в while не менять переменную из условия, цикл крутится вечно. Всегда проверяйте, что тело приближает условие к завершению.
  • Перепутали смысл until. repeat останавливается, когда условие истинно, а while — когда ложно. Это противоположные логики.
  • Лишние begin/end в repeat. Внутри repeat...until составной оператор не нужен — конструкция сама ограничивает блок.
  • Одна переменная на два вложенных цикла. Внешнему и внутреннему циклу нужны разные счётчики (i и j).

Итоги

  • while условие do проверяет условие в начале и повторяет тело, пока оно истинно (может не выполниться ни разу).
  • repeat ... until условие проверяет условие в конце, тело выполняется минимум один раз и повторяется, пока условие ложно.
  • В цикле по условию обязательно меняйте переменную, влияющую на условие, иначе программа зациклится.
  • Вложенные циклы (цикл внутри цикла) нужны для таблиц и матриц; у каждого свой счётчик.
  • break досрочно выходит из цикла, continue пропускает остаток шага и переходит к следующему.
Проверьте себя
1. В чём ключевое различие while и repeat?
Awhile проверяет условие в начале, repeat — в конце
Bwhile работает только с числами, repeat — со строками
Crepeat быстрее while
DРазличий нет
2. Что произойдёт, если в цикле while не менять переменную из условия?
AЦикл выполнится ровно один раз
BЦикл не выполнится вовсе
CПрограмма зациклится и будет работать бесконечно
DПаскаль автоматически остановит цикл
3. Что делает команда break внутри цикла?
AПропускает остаток текущего шага и переходит к следующему
BНемедленно полностью выходит из цикла
CПерезапускает цикл с начала
DУдваивает счётчик
Поддержать проект