Глиф Учебники

Урок 5. Циклы — while, for, foreach

Курс «C#» · урок 5 из 10 · 3 минуты чтения

Цикл повторяет одни и те же команды, пока выполняется условие. Без циклов, чтобы сложить числа от 1 до 100, пришлось бы написать сто строк. В C# четыре вида циклов: while, do-while, for и foreach.

while — пока условие истинно

C#
int n = int.Parse(Console.ReadLine() ?? "");
int digits = 0;
int sum = 0;
while (n > 0)
{
    sum += n % 10;
    n /= 10;
    digits++;
}
Console.WriteLine($"Цифр: {digits}, сумма цифр: {sum}");
Ввод
2024
Вывод
Цифр: 4, сумма цифр: 8

while проверяет условие перед каждым повтором. Здесь на каждом шаге n % 10 даёт последнюю цифру, а n /= 10 её отбрасывает: 2024 → 202 → 20 → 2 → 0. Когда n становится 0, условие ложно, и цикл заканчивается. Каждое выполнение тела цикла называют итерацией.

n sum += n % 10; n /= 10; digits++; 2024 0 + 4 = 4 202 1 202 4 + 2 = 6 20 2 20 6 + 0 = 6 2 3 2 6 + 2 = 8 0 4 0 n > 0 ложно — цикл закончен: сумма 8, цифр 4
Четыре итерации цикла while для числа 2024: последняя цифра уходит в сумму, число укорачивается на одну цифру, счётчик цифр растёт, пока n не станет 0.

Если условие ложно с самого начала, тело не выполнится ни разу: для n = 0 программа скажет, что цифр 0. С отрицательным числом будет то же самое (условие n > 0 сразу ложно), поэтому его сначала делают положительным: n = Math.Abs(n);.

do-while — сначала сделать, потом проверить

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

C#
int number;
do
{
    Console.Write("Введите число от 1 до 10: ");
    number = int.Parse(Console.ReadLine() ?? "");
}
while (number < 1 || number > 10);
Console.WriteLine($"Принято: {number}");
Текст
Введите число от 1 до 10: 15
Введите число от 1 до 10: 0
Введите число от 1 до 10: 7
Принято: 7

for — со счётчиком

Когда заранее известно, сколько раз повторять, удобен for. В его скобках три части через ;: начальное значение счётчика, условие продолжения и шаг.

C#
int sum = 0;
for (int i = 1; i <= 100; i++)
{
    sum += i;
}
Console.WriteLine(sum);
Вывод
5050
for (int i = 1; i <= 100; i++) 1 2 3 1 int i = 1 один раз в начале 2 i <= 100 да sum += i; тело цикла 3 i++ после каждого шага снова проверка нет Console.WriteLine(sum); при i = 101 условие ложно, сумма 5050
Три части заголовка for: начальное значение задаётся один раз, условие проверяется перед каждой итерацией, а i++ выполняется после тела, и снова идёт проверка.

Порядок такой: int i = 1 выполняется один раз; затем перед каждой итерацией проверяется i <= 100; после каждой итерации выполняется i++. Шаг может быть любым:

C#
for (int i = 10; i > 0; i -= 3)
{
    Console.WriteLine(i);
}
Вывод
10
7
4
1

Переменная i, объявленная в скобках for, существует только внутри цикла. После цикла её уже нет; если значение нужно и дальше, объявите переменную до цикла.

foreach — по каждому элементу

foreach проходит по всем элементам набора — строки, массива, списка — без всякого счётчика:

C#
string word = "шарп";
foreach (char c in word)
{
    Console.WriteLine(c);
}
Вывод
ш
а
р
п

Читается так: «для каждого символа c в строке word». С массивами и списками foreach встретится в следующем уроке. Менять элементы набора через переменную foreach нельзя — она только для чтения.

break и continue

C#
for (int i = 1; i <= 10; i++)
{
    if (i % 3 == 0)
    {
        continue;
    }
    if (i > 7)
    {
        break;
    }
    Console.WriteLine(i);
}
Вывод
1
2
4
5
7

Числа 3 и 6 пропущены из-за continue. На восьмёрке срабатывает break, и до 9 и 10 цикл уже не доходит.

for (int i = 1; i <= 10; i++) 1 2 3 4 5 6 7 8 9 10 continue пропуск continue пропуск break выход не дошло на экране: 1 2 4 5 7
На тройке и шестёрке continue пропускает печать и цикл идёт дальше, на восьмёрке break завершает цикл, поэтому до 9 и 10 он не доходит.

Цикл while (true) сам не заканчивается никогда — из него выходят через break. Так часто пишут, когда условие выхода удобнее проверить в середине тела, например «читать числа, пока не введут 0».

Цикл в цикле

Внутри цикла может быть другой цикл. Внутренний проходит целиком на каждой итерации внешнего:

C#
for (int row = 1; row <= 3; row++)
{
    for (int col = 1; col <= 4; col++)
    {
        Console.Write($"{row * col,4}");
    }
    Console.WriteLine();
}
Вывод
   1   2   3   4
   2   4   6   8
   3   6   9  12

{row * col,4} печатает число в поле шириной 4 знака — так столбцы получаются ровными. После каждой строки Console.WriteLine() переводит строку.

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

Коротко

Проверьте себя

1. Сколько раз выполнится тело цикла for (int i = 0; i < 5; i++)?
2. Чем do-while отличается от while?
3. Что выведет программа?
C#
int s = 0;
for (int i = 1; i <= 5; i++)
{
    if (i == 3)
    {
        continue;
    }
    s += i;
}
Console.WriteLine(s);
4. Как остановить программу, которая зависла в бесконечном цикле в терминале?