Перейти к содержимому
Теория · Циклы · урок 1 из 8

for, while и do-while

Чему вы научитесь

Чему вы научитесь:

  • повторять действие циклами for, while и do-while;
  • считать, сколько раз выполнится цикл, и не ошибаться на единицу;
  • проходить по списку значений циклом по диапазону;
  • досрочно выходить из цикла через break и пропускать итерацию через continue.
Беговая дорожка: старт int i = 1, контрольная арка i <= 5 перед каждым кругом и отметка ++i в блокноте после круга

Чтобы напечатать числа от 1 до 5, можно написать пять строк с std::cout. Для тысячи чисел понадобилась бы тысяча строк. Вместо этого пишут цикл — конструкцию, которая повторяет действие, пока выполняется условие.

Представьте бегуна на стадионе. Тренер говорит: «Бегай круги, пока не пробежишь пять».

Бегун встаёт на линию старта. Перед каждым кругом он пробегает под контрольной аркой, и та проверяет, сколько кругов уже сделано. Потом бегун пробегает круг и ставит отметку в блокноте. Цикл устроен так же:

C++
#include <iostream>

int main() {
    for (int i = 1; i <= 5; ++i) {
        std::cout << i << ' ';  // 1 2 3 4 5
    }
    std::cout << '\n';
}

Как работает цикл for

В заголовке for три части через точку с запятой. Каждая похожа на свою часть стадиона, и выполняются они в таком порядке:

  1. Инициализация int i = 1 выполняется один раз, до начала цикла. Это линия старта.
  2. Условие i <= 5 проверяется перед каждым проходом. Это контрольная арка: если условие истинно, выполняется тело, а если ложно, цикл заканчивается.
  3. Тело в фигурных скобках выполняется. Это сам круг.
  4. Шаг ++i выполняется после тела. Это отметка в блокноте. Затем цикл возвращается к пункту 2.

В виджете тот же цикл с условием i <= 3: нажмите «Следующий шаг» и следите, когда выполняется каждая часть заголовка.

ВживуюПорядок частей forшаг 1 из 11 · рамок: 1

Инициализация int i = 1 выполняется один раз

Рамка — место, где живут переменные одного вызова

Один проход тела называют итерацией. Здесь аналогия заканчивается: настоящий бегун сам знает, сколько пробежал, а цикл помнит только значение i.

Когда i становится равной 6, условие ложно, и цикл заканчивается. Переменная i объявлена в заголовке, поэтому видна только внутри цикла. После закрывающей фигурной скобки тела цикла имени i уже нет.

Сколько итераций

Цикл выполняется столько раз, сколько значений принимает счётчик i. В for (int i = 0; i < 5; ++i) это значения от 0 до 4, то есть пять итераций. Знак < не пускает i к самой границе.

Если заменить < на <=, i дойдёт и до 5, и итераций станет шесть. Цикл, который выполняется на один раз больше или меньше нужного, содержит ошибку на единицу. На собеседовании такие циклы часто дают с вопросом «сколько раз выполнится тело?».

Циклы while и do-while

У for все три части стоят в заголовке. Два других вида цикла устроены проще.

Цикл while

Цикл while проверяет условие перед каждой итерацией, как for, но инициализации и шага в нём нет. Переменную объявляют до цикла, а меняют в теле. Его выбирают, когда число итераций заранее неизвестно. Так можно посчитать, сколько раз 100 нужно разделить нацело на 2, чтобы осталась 1:

C++
int n = 100;
int steps = 0;
while (n > 1) {
    n = n / 2;
    ++steps;
}
std::cout << steps << '\n';  // 6

Значения n идут так: 100, 50, 25, 12, 6, 3, 1. Делений шесть, и на 1 условие n > 1 становится ложным.

Цикл do-while

Цикл do-while сначала выполняет тело и только потом проверяет условие. Поэтому его тело выполняется хотя бы один раз, даже если условие ложно с самого начала. Сравните два цикла с одним и тем же ложным условием:

C++
int n = 10;
while (n < 5) {
    std::cout << n << '\n';
    ++n;
}
do {
    std::cout << n << '\n';  // 10
    ++n;
} while (n < 5);

Давайте разберём, что происходит:

  1. while сразу проверяет 10 < 5. Условие ложно, тело не выполняется, и ничего не печатается.
  2. do выполняет тело: печатает 10 и делает n равной 11.
  3. Только теперь проверяется n < 5. Условие ложно, и цикл заканчивается.

Цикл do-while заканчивается точкой с запятой после while (n < 5). Без неё программа не скомпилируется.

Частая ошибка

Счётчик типа unsigned в цикле обратного отсчёта:

C++
for (unsigned i = 3; i >= 0; --i) {  // ✗
    std::cout << i << '\n';
}

Значение unsigned не бывает отрицательным, поэтому условие i >= 0 истинно всегда. Если вычесть единицу из 0, получится наибольшее значение unsigned, и цикл печатает числа без конца. GCC с флагом -Wextra предупреждает, что сравнение всегда истинно, а Clang даже с -Wextra молчит. Для отсчёта до нуля объявите счётчик как int: после 0 он станет равен -1, и условие окажется ложным.

Главное

  • Части заголовка for выполняются по порядку: инициализация один раз, затем условие, тело, шаг и снова условие.
  • Цикл с i = 0 и условием i < n выполняется n раз, а с <= — на один раз больше.
  • while проверяет условие до тела, а do-while — после, поэтому его тело выполняется хотя бы раз.
  • Счётчик unsigned никогда не станет меньше нуля, и условие i >= 0 с ним истинно всегда.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом