Перейти к содержимому
Теория · Условия и циклы · урок 6 из 13

while и do-while

Представьте бегуна на стадионе. Тренер говорит: «Бегай круги, пока не стемнеет». Перед каждым новым кругом бегун проходит под аркой у старта и смотрит на небо: ещё светло — бежит следующий круг, стемнело — сходит с дорожки. Сколько будет кругов, заранее не знает никто.

Программе тоже часто нужно повторять одно и то же действие. Для повторения есть цикл — конструкция, которая выполняет свой код снова и снова, пока условие истинно. Начнём с цикла while. Программа ниже считает, сколько раз число 100 можно разделить пополам, пока не останется 1:

C#
int n = 100;
int steps = 0;

while (n > 1)
{
    n /= 2;
    steps++;
}

Console.WriteLine(steps); // 6

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

  1. int n = 100; и int steps = 0; заводят число и счётчик делений.
  2. while (n > 1) проверяет условие: 100 > 1 истинно, поэтому выполняется код в фигурных скобках — тело цикла.
  3. Тело делит n пополам и прибавляет к steps единицу.
  4. Потом цикл возвращается к условию и проверяет его снова, уже с новым n.
  5. Значения n идут так: 100, 50, 25, 12, 6, 3, 1. На 1 условие n > 1 ложно, и цикл заканчивается.
  6. Console.WriteLine(steps) стоит после цикла и выводит 6: столько было делений.

Один проход тела цикла называют итерацией. В этой программе шесть итераций, по одной на каждое деление.

Как работает while

Цикл while повторяет два шага:

  1. Проверить условие.
  2. Если оно истинно, выполнить тело и вернуться к шагу 1. Если ложно, перейти к коду после цикла.

Условие проверяется и перед самой первой итерацией. Если оно ложно сразу, тело не выполнится ни разу: при n = 1 программа выведет 0.

while берут, когда число повторений заранее неизвестно и зависит от того, что происходит в теле. Так и бегун не знает, сколько кругов успеет до темноты.

Цикл, который не кончается

Если тело не меняет переменную из условия, условие остаётся истинным, и цикл не заканчивается никогда. Уберите из примера строку n /= 2;, и n навсегда останется равной 100. Программа будет крутить цикл, пока вы её не остановите: в терминале для этого нажмите Ctrl+C.

Здесь картинка со стадионом неточна. Бегун рано или поздно устанет и сойдёт с дорожки сам, а цикл без изменения переменной будет крутиться вечно.

Цикл do-while

У while есть родственник — цикл do. Его записывают так: do { тело } while (условие);. Он проверяет условие после тела, поэтому тело выполняется хотя бы один раз. Бегун сначала пробегает круг и только потом смотрит на небо.

Цикл do подходит для подсчёта цифр числа. У числа 0 одна цифра, и цикл должен это учесть:

C#
int n = 0;
int digits = 0;

do
{
    digits++;
    n /= 10;
}
while (n > 0);

Console.WriteLine(digits); // 1

Разберём по шагам:

  1. Тело выполняется сразу, без проверки: digits становится равной 1, а n /= 10 оставляет в n значение 0.
  2. Только теперь проверяется условие n > 0. Оно ложно, и цикл заканчивается.
  3. Программа выводит 1: у числа 0 одна цифра.

С обычным while условие n > 0 проверилось бы до тела. Тело не выполнилось бы ни разу, и программа вывела бы неверный ответ 0. Для n = 4096 оба цикла дают 4: отличаются они только тогда, когда условие ложно с самого начала.

Обратите внимание на конец цикла: после while (n > 0) в цикле do стоит точка с запятой, а у обычного while её нет.

На собеседовании часто спрашивают, чем цикл while отличается от цикла do. Разница в том, когда проверяется условие: while проверяет его перед телом, а do — после, поэтому тело do выполняется хотя бы один раз.

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

Фигурные скобки вокруг тела цикла пропустили, а обе строки тела выровняли отступом:

C#
int n = 100;
int steps = 0;

while (n > 1)
    n /= 2;
    steps++; // ✗

Console.WriteLine(steps);

Программа компилируется без ошибок и предупреждений, но выводит 1, а не 6.

Без фигурных скобок тело цикла — одна инструкция, n /= 2;. Компилятор не смотрит на отступы, поэтому steps++; стоит уже после цикла и выполняется один раз. Верните фигурные скобки вокруг обеих строк, как в первом примере.

Главное

  • while проверяет условие перед каждой итерацией и выполняет тело, пока условие истинно.
  • Тело должно менять переменную из условия, иначе цикл не закончится.
  • Цикл do проверяет условие после тела, поэтому тело выполняется хотя бы один раз.
  • Без фигурных скобок тело цикла — только первая инструкция после условия, какими бы ни были отступы.