Содержание
В прошлой статье мы разобрали условные конструкции и научили программу выбирать, какой код выполнять, с помощью if, else if, switch и тернарного оператора.
Но пока каждая строчка наших программ выполняется не больше одного раза. А что, если одно и то же действие нужно повторить пять, тысячу или миллион раз? Или повторять его до тех пор, пока пользователь не введёт правильное значение? Для этого в C++ есть циклы.
В этой статье мы разберём все три цикла — while, do while и for, — операторы break и continue, которые меняют стандартное поведение циклов, а также бесконечные циклы: когда это ошибка, а когда полезный приём.
После этой статьи Вы сможете:
- объяснить, что такое цикл, тело цикла и итерация;
- повторять действия с помощью циклов
while,do whileиfor; - понимать, чем цикл с предусловием отличается от цикла с постусловием;
- задавать в цикле
forлюбой шаг и понимать, в каком порядке выполняются его части; - управлять циклом изнутри с помощью
breakиcontinue; - находить и исправлять бесконечные циклы, а когда нужно — писать их намеренно;
- выбирать цикл, который лучше всего подходит под задачу.
Зачем нужны циклы
Начнём с задачи: нужно вывести на экран числа от 1 до 5, каждое с новой строки. С тем, что мы уже знаем, её можно решить так:
#include <iostream>
int main() {
std::cout << 1 << "\n";
std::cout << 2 << "\n";
std::cout << 3 << "\n";
std::cout << 4 << "\n";
std::cout << 5 << "\n";
return 0;
}
1
2
3
4
5
Программа работает, но у такого решения есть очевидные проблемы. Что, если чисел нужно вывести не 5, а 1000 или миллион? Копировать строку с std::cout тысячу раз долго, а ошибиться в одной из копий легко.
А если количество чисел вводит пользователь? Он вводит некоторое n, и нужно вывести числа от 1 до n. Тогда мы даже не знаем заранее, сколько строк с std::cout понадобится. Решение «в лоб» здесь не работает: такую задачу правильно решать с помощью цикла.
Что такое цикл
Цикл — это конструкция, которая повторяет одни и те же действия, пока верно некоторое условие. Пока на условие мы отвечаем «да», действия выполняются снова и снова.
Запомним ещё два определения, которые будут встречаться постоянно:
- тело цикла — действия, которые повторяются, пока условие истинно;
- итерация — одно полное выполнение тела цикла. Если тело выполнилось три раза, говорят, что цикл сделал три итерации.
В C++ три цикла: while, do while и for. Забегая вперёд: нет задачи, которую можно решить только одним из них. Любой цикл можно заменить любым другим, просто одни задачи удобнее решать одним циклом, а другие — другим. Разберём все три по очереди, а в конце обсудим, какой когда выбирать.
Цикл while
Цикл while (по-английски «пока») — самый простой и один из самых популярных. Его блок-схема очень похожа на блок-схему условного оператора if из прошлого урока, но с одним важным отличием: после выполнения тела цикла программа не идёт дальше, а возвращается к проверке условия.
Если на условие мы отвечаем «да», выполняется тело цикла, и мы снова идём проверять условие. Если отвечаем «нет», цикл завершается и программа переходит к коду после него.
Синтаксис while
while (условие) {
// тело цикла
}
После ключевого слова while в круглых скобках записывается логическое выражение, а в фигурных скобках — тело цикла. Пока логическое выражение истинно, тело цикла выполняется.
Пример: числа от 1 до 5
Решим нашу задачу с помощью while. До цикла объявим переменную i, равную 1. Пока i меньше или равна 5, будем выводить её на экран и увеличивать на 1:
#include <iostream>
int main() {
int i = 1;
while (i <= 5) {
std::cout << i << "\n";
i++;
}
return 0;
}
1
2
3
4
5
Переменную i называют счётчиком цикла: она хранит текущее число и меняется на каждой итерации.
Разбор цикла while по шагам
Разберём этот пример подробно. Чтобы таблица получилась короче, пусть цикл идёт не до 5, а до 3:
int i = 1;
while (i <= 3) {
std::cout << i << "\n";
i++;
}
Построим таблицу из трёх столбцов: значение i, результат проверки условия и вывод на экран.
i | i <= 3 | Вывод |
|---|---|---|
| 1 | true | 1 |
| 2 | true | 2 |
| 3 | true | 3 |
| 4 | false | цикл завершён |
Сначала объявляем i, равную 1, и проверяем условие: 1 меньше или равно 3 — истина. Заходим в тело цикла, выводим 1 и увеличиваем i до 2. Одна итерация прошла, и мы возвращаемся к проверке условия.
2 ≤ 3 — снова истина: выводим 2, i становится равной 3. 3 ≤ 3 — истина: выводим 3, i становится равной 4. Наконец, 4 ≤ 3 — ложь. Условие стало ложным, и цикл завершается.
Итого на экране числа 1, 2 и 3, каждое с новой строки. Тело цикла выполнилось три раза, то есть цикл сделал три итерации. Условие при этом проверялось четыре раза: последняя проверка и завершила цикл.
Главное о цикле while
- условие проверяется перед каждой итерацией;
- если условие ложно с самого начала, тело цикла не выполнится ни разу. Например, если
iизначально равна 5, а условие —i <= 3, цикл не сделает ни одной итерации. Поэтомуwhileназывают циклом с предусловием; - в теле цикла должно меняться то, от чего зависит условие. В нашем примере условие зависит от
iи от константы 3. Константа не меняется, значит, менять нужноi, иначе цикл никогда не закончится.
i++ и ++i в условии while
Инкремент можно записать прямо в условии цикла. Такой пример могут показать в школе или в институте, поэтому важно понимать, как он работает. Вспомним прошлый урок: постфиксный инкремент i++ сначала отдаёт в выражение текущее значение переменной и только потом увеличивает её, а префиксный ++i сначала увеличивает переменную, а потом использует уже новое значение.
#include <iostream>
int main() {
int i = 0;
while (i++ < 3) {
std::cout << i << "\n";
}
return 0;
}
1
2
3
При первой проверке сравнивается текущее значение: 0 < 3 — истина. Сразу после проверки i увеличивается до 1, поэтому в теле цикла выводится 1. Затем 1 < 3 — истина, i становится равной 2, выводим 2. Затем 2 < 3 — истина, выводим 3. Наконец, 3 < 3 — ложь, и цикл завершается. Но i всё равно увеличивается: если вывести её после цикла, мы увидим 4.
Теперь заменим постфиксный инкремент на префиксный:
int i = 0;
while (++i < 3) {
std::cout << i << "\n";
}
1
2
На первый взгляд кажется, что результат будет тем же, но это не так. Сначала i увеличивается до 1, и только потом проверяется условие 1 < 3 — выводим 1. Затем i становится равной 2, условие истинно — выводим 2. Затем i становится равной 3, и условие 3 < 3 ложно. Тело цикла выполнилось только два раза.
Бесконечный цикл
Посмотрим, что будет, если забыть увеличить счётчик внутри цикла:
int i = 1;
while (i <= 3) {
std::cout << i << "\n";
}
i равна 1, условие 1 ≤ 3 истинно — выводим 1 и возвращаемся к проверке. i по-прежнему равна 1, условие снова истинно — снова выводим 1. И так без конца: условие никогда не станет ложным, и программа бесконечно печатает единицы.
1
1
1
1
1
...
Цикл, условие которого никогда не становится ложным, называется бесконечным. Чаще всего бесконечный цикл — это ошибка: Вы что-то забыли. Но не всегда.
Например, любая компьютерная игра — это бесконечный цикл. Он раз за разом обрабатывает нажатия клавиш, просчитывает логику игры и отрисовывает следующий кадр. Если игра работает с частотой 60 кадров в секунду, этот цикл выполняется примерно 60 раз в секунду, пока игрок не выйдет из игры. Ниже мы посмотрим, как намеренно написать бесконечный цикл и правильно из него выйти.
Цикл do while
Рассмотрим задачу: попросим пользователя ввести число от 1 до 10. Если он введёт что-то не то, например число меньше 1 или больше 10, попросим ввести число ещё раз.
Похожая ситуация бывает, когда программа спрашивает возраст: он не может быть меньше 0 или больше 150 лет. Если пользователь ввёл число вне этого диапазона, скорее всего, он ошибся, и нужно спросить ещё раз.
Чем эта задача отличается от задач для while? Здесь сначала нужно выполнить действие — ввести число — и только потом проверить, нужно ли вводить его ещё раз. Для таких задач есть цикл do while.
В do while тело цикла выполняется до первой проверки условия. Если на условие мы отвечаем «да», тело выполняется ещё раз, и так до тех пор, пока условие не станет ложным. В while всё наоборот: сначала условие, потом тело.
Синтаксис do while
do {
// тело цикла
} while (условие);
Сначала пишем ключевое слово do, затем в фигурных скобках тело цикла, после него while и в круглых скобках уже знакомое логическое выражение.
Пример: просим число от 1 до 10
#include <iostream>
int main() {
int number;
do {
std::cout << "Введите число от 1 до 10: ";
std::cin >> number;
} while (number < 1 || number > 10);
return 0;
}
Посмотрите на условие: number < 1 || number > 10. Оно истинно, когда пользователь ввёл неподходящее число, например −100 или 100. Тогда нужно выполнить ещё одну итерацию: снова попросить ввести число. Как только пользователь введёт число от 1 до 10, условие станет ложным, и цикл завершится.
Введите число от 1 до 10: 100
Введите число от 1 до 10: -5
Введите число от 1 до 10: 7
Чем while отличается от do while
Главное отличие — в моменте проверки условия. Чтобы его увидеть, возьмём условие, которое ложно с самого начала. В обоих циклах объявим i, равную 10, и будем повторять тело, пока i < 5:
int i = 10;
while (i < 5) {
std::cout << i << "\n";
i++;
}
int i = 10;
do {
std::cout << i << "\n";
i++;
} while (i < 5);
Цикл while сначала проверяет условие: 10 < 5 — ложь. Он не выполнит ни одной итерации и даже не зайдёт в тело цикла.
Цикл do while сначала выполняет тело: выводит 10 и увеличивает i до 11. Только потом он проверяет условие 11 < 5 — ложь, и цикл завершается.
Получается, что while выполняет 0 и более итераций, а do while — всегда хотя бы одну. Поэтому while называют циклом с предусловием, а do while — циклом с постусловием.
while | do while | |
|---|---|---|
| Когда проверяется условие | перед телом цикла | после тела цикла |
| Как называется | цикл с предусловием | цикл с постусловием |
| Сколько итераций | 0 и более | 1 и более |
Когда нужен while, а когда do while
Цикл do while удобен, когда действие нужно выполнить хотя бы один раз. Например, получить от пользователя ввод и повторять просьбу, пока он не введёт корректные данные. Цикл while подходит, когда заранее неизвестно, нужно ли выполнять действие вообще.
Разницу помогают запомнить два примера. Представьте, что Вы на берегу моря и хотите наполнить надувной бассейн морской водой. Как человек разумный, Вы сначала посмотрите, не наполнен ли он уже: вдруг его наполнил сотрудник отеля или прошёл дождь. И только если воды нет, возьмёте ведро. Сначала проверяем, нужно ли действовать, и только потом действуем — это while.
А теперь представьте, что Вы ищете в библиотеке книгу Виктора Гюго «Отверженные», а на корешках старых книг ничего не написано. Вы точно возьмёте хотя бы одну книгу и посмотрите автора и название. Если это не она, поставите её на место и возьмёте следующую — и так, пока не найдёте нужную. Сначала действуем, потом проверяем — это do while.
Стоит сказать и о том, что do while используется заметно реже, чем while и for. В некоторых популярных языках, например в Python и Go, такого цикла нет совсем. Но иногда он действительно удобен.
Цикл for
Последний цикл — for, самый популярный из трёх. Его популярность во многом связана с массивами: перебирать их элементы удобнее всего именно циклом for. Массивы мы разберём в следующем уроке, а пока посмотрим, какую задачу решает этот цикл.
Вернёмся к циклу while, который выводил числа по порядку. В любом цикле со счётчиком есть три части:
int i = 1; // инициализация
while (i <= 5) { // условие
std::cout << i << "\n";
i++; // шаг
}
- инициализация — создаём счётчик и задаём ему начальное значение;
- условие — пока оно истинно, выполняется тело цикла;
- шаг — изменение счётчика после каждой итерации.
В цикле while эти части разбросаны по разным строкам. Цикл for собирает их в одной строке, и код со счётчиком читается легче.
Синтаксис for
for (инициализация; условие; шаг) {
// тело цикла
}
В заголовке цикла for три секции: инициализация, условие и шаг. Они обязательно разделяются точками с запятой — эти точки с запятой нельзя пропускать. После заголовка в фигурных скобках записывается тело цикла.
Перепишем вывод чисел от 1 до 5 с помощью for:
#include <iostream>
int main() {
for (int i = 1; i <= 5; i++) {
std::cout << i << "\n";
}
return 0;
}
1
2
3
4
5
Порядок выполнения цикла for
- инициализация
int i = 1выполняется один раз — до первой проверки условия; - условие
i <= 5проверяется перед каждой итерацией — так же, как вwhile; - если условие истинно, выполняется тело цикла;
- после каждой итерации выполняется шаг
i++, и мы возвращаемся к пункту 2.
Получается цепочка 1 → 2 → 3 → 4 → 2 → 3 → 4 → 2 → 3 → 4… Условие, тело, шаг — и так снова и снова, пока условие истинно. Как только оно становится ложным, цикл завершается.
Шаг цикла может быть любым
В секции шага не обязательно писать i++. Шаг может быть отрицательным: начнём с 5 и будем уменьшать i, пока она больше 0. Получим числа в обратном порядке, а 0 не выведется, потому что условие 0 > 0 ложно:
for (int i = 5; i > 0; i--) {
std::cout << i << " ";
}
5 4 3 2 1
Шаг может быть больше единицы. Выведем числа от 0 до 10 включительно с шагом 2:
for (int i = 0; i <= 10; i += 2) {
std::cout << i << " ";
}
0 2 4 6 8 10
Шагом может быть даже умножение. Будем удваивать i, пока она не превысит 2000:
for (int i = 2; i <= 2000; i *= 2) {
std::cout << i << " ";
}
2 4 8 16 32 64 128 256 512 1024
В шаге можно использовать не только константы, но и переменные. Например, шаг может ввести пользователь:
#include <iostream>
int main() {
int a;
std::cin >> a;
for (int i = 2; i <= 2000; i += a) {
std::cout << i << " ";
}
return 0;
}
100
2 102 202 302 402 502 602 702 802 902 1002 1102 1202 1302 1402 1502 1602 1702 1802 1902
Необязательные секции for
Ни одна из трёх секций цикла for не обязательна, а вот точки с запятой обязательны всегда. Если оставить все секции пустыми, получится бесконечный цикл:
for (;;) {
std::cout << "hello\n";
}
Такая программа будет бесконечно выводить слово hello, пока её не остановить.
Можно объявить счётчик до цикла, а шаг перенести в тело:
int i = 1;
for (; i <= 5;) {
std::cout << i << "\n";
++i;
}
Если заменить здесь for на while и убрать точки с запятой, получится уже знакомый цикл while. Это ещё одно подтверждение того, что любой цикл можно заменить другим. Но так писать не принято: если используете for, объявляйте счётчик в секции инициализации, а шаг пишите в секции шага — так код чище.
Другие типы и несколько переменных в заголовке for
Следующие возможности нужны редко, но о них полезно знать. В секции инициализации можно объявить переменную любого типа, например double:
for (double i = 1.5; i < 6.7; i += 0.5) {
std::cout << i << " ";
}
1.5 2 2.5 3 3.5 4 4.5 5 5.5 6 6.5
Или переменную типа char — тогда цикл переберёт буквы алфавита:
for (char c = 'a'; c <= 'z'; c++) {
std::cout << c;
}
abcdefghijklmnopqrstuvwxyz
Если в условии написать c < 'z', последняя буква z не выведется. Но чаще всего счётчиком цикла всё же бывает переменная типа int.
В секции инициализации можно объявить несколько переменных через запятую, но все они должны быть одного типа. Условие может быть составным, а в секции шага можно выполнять несколько действий, тоже через запятую:
for (int i = 0, j = 10; i < j && j > 5; ++i, --j) {
std::cout << i << " " << j << "\n";
}
0 10
1 9
2 8
3 7
4 6
В условии и в шаге можно использовать и переменные, объявленные до цикла:
int counter = 0;
for (int i = 0; counter < 1000; ++i, ++counter) {
// ...
}
Такие конструкции встречаются нечасто, но теперь они Вас не удивят.
Пример: сумма чисел от 1 до n
Решим более жизненную задачу: посчитаем сумму чисел от 1 до n, где n вводит пользователь.
#include <iostream>
int main() {
int n;
std::cin >> n;
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
std::cout << sum;
return 0;
}
Разберём программу по шагам для n = 3. До цикла сумма равна 0: мы ещё ничего не сложили.
i | i <= n | sum |
|---|---|---|
| 1 | true | 1 |
| 2 | true | 3 |
| 3 | true | 6 |
| 4 | false | цикл завершён |
Секция инициализации создаёт i, равную 1. Условие 1 ≤ 3 истинно — прибавляем 1 к сумме. Шаг увеличивает i до 2, условие истинно — сумма становится равной 3. Затем i равна 3 — сумма равна 6. Наконец, i становится равной 4, условие 4 ≤ 3 ложно, цикл завершается, и программа выводит 6.
3
6
i++ или ++i в шаге цикла for
В секции шага цикла for неважно, что писать: i++ или ++i. И постфиксный, и префиксный инкремент увеличат i на единицу, а значение самого выражения здесь нигде не используется. Это дело вкуса: многие программисты предпочитают писать ++i.
Операторы break и continue
Иногда стандартное поведение цикла нужно изменить изнутри: досрочно завершить цикл или пропустить часть итерации. Для этого есть два оператора — break и continue.
Оператор break
break немедленно завершает цикл.
#include <iostream>
int main() {
for (int i = 1; i <= 5; i++) {
if (i == 3) {
break;
}
std::cout << i << " ";
}
return 0;
}
1 2
Разберём по шагам. При i = 1 условие i == 3 ложно — выводим 1. При i = 2 — выводим 2. При i = 3 условие истинно, выполняется break, и цикл сразу завершается: не заканчивается ни текущая итерация, ни последующие. Числа 3, 4 и 5 на экран не попадут.
Оператор continue
continue, в отличие от break, не завершает цикл. Он пропускает оставшуюся часть тела цикла и переходит к следующей итерации.
#include <iostream>
int main() {
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue;
}
std::cout << i << " ";
}
return 0;
}
1 2 4 5
При i = 1 и i = 2 всё происходит так же, как в прошлом примере. При i = 3 выполняется continue: вывод пропускается, и цикл for сразу переходит к шагу i++ и проверке условия. Дальше выводятся 4 и 5.
| Оператор | Что делает | Вывод в примере |
|---|---|---|
break | досрочно завершает цикл | 1 2 |
continue | пропускает остаток текущей итерации и продолжает цикл | 1 2 4 5 |
Операторы break и continue работают не только в цикле for, но и в while и do while, и ведут себя там точно так же.
while (true) и break
Посмотрим, когда ещё полезен break. Задача: суммировать числа, которые пользователь вводит с клавиатуры, пока он не введёт 0.
Мы не знаем, сколько чисел введёт пользователь: он может сразу ввести 0, а может ввести сто чисел и только потом 0. Поэтому цикл for здесь не очень удобен — он хорош, когда заранее известно, сколько раз нужно повторить действие. Здесь подойдёт while или do while.
#include <iostream>
int main() {
int x;
int sum = 0;
while (true) {
std::cin >> x;
if (x == 0) {
break;
}
sum += x;
}
std::cout << sum;
return 0;
}
Условие true истинно всегда, поэтому while (true) — это сознательно написанный бесконечный цикл. Такой подход часто используют в программировании. На каждой итерации вводим x: если он равен 0, выходим из цикла с помощью break, а иначе прибавляем x к сумме.
5 3 -2 10 0
16
Задачи такого типа ждут Вас и в контесте к этому уроку.
Какой цикл выбрать
| Цикл | Когда удобен | Пример |
|---|---|---|
for | известно, сколько раз нужно повторить тело цикла | вывести числа от 0 до 5, пройти от 100 до 0 с шагом −10 |
while | неизвестно, сколько раз повторять, но известно, до каких пор; условие нужно проверить до первой итерации | суммировать числа, пока пользователь не введёт 0; наполнять бассейн, пока он не полон |
do while | то же, что while, но тело нужно выполнить хотя бы один раз | запросить ввод и повторять, пока данные некорректны; искать книгу в библиотеке |
И ещё раз главное: любой цикл можно переписать через любой другой. Нет задачи, которую можно решить только с помощью for, while или do while. Выбирайте тот цикл, с которым код получается понятнее.
Подведём итоги
В этой статье Вы познакомились со всеми тремя циклами C++ и с операторами, которые меняют их поведение.
Главное, что нужно запомнить:
- цикл повторяет действия, пока условие истинно. Повторяемые действия — это тело цикла, а одно его выполнение — итерация;
whileпроверяет условие перед каждой итерацией и может не выполниться ни разу — это цикл с предусловием;do whileсначала выполняет тело, а потом проверяет условие, поэтому делает хотя бы одну итерацию — это цикл с постусловием. Не забывайте точку с запятой послеwhile (условие);forсобирает инициализацию, условие и шаг в одной строке. Шаг может быть любым, а любую из секций можно опустить;- в условии
whileразница междуi++и++iвлияет на количество итераций, а в шагеfor— нет; breakдосрочно завершает цикл, аcontinueпропускает остаток текущей итерации;- бесконечный цикл чаще всего ошибка: проверьте, меняется ли переменная из условия. Но
while (true)вместе сbreak— полезный приём; - любой цикл можно заменить любым другим — выбирайте тот, с которым код понятнее.
Теория без практики быстро забывается, поэтому обязательно закрепите материал. Авторизуйтесь на сайте, отметьте статью как прочитанную и перейдите во вкладку «Решать задачи». Отправляйте решения на проверку, разбирайте результаты тестов и отслеживайте свой прогресс.
Использованная литература
- Рабочий проект стандарта C++ [Электронный ресурс]. — URL: https://eel.is/c++draft/ (дата обращения: 14.10.2026).
- Рабочий проект стандарта C++26 — N5054 [Электронный ресурс]. — URL: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/n5054.pdf (дата обращения: 14.10.2026).
- ISO/IEC 14882:2024 — язык программирования C++ [Электронный ресурс]. — URL: https://www.iso.org/standard/83626.html (дата обращения: 14.10.2026).
- Цикл while [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/while (дата обращения: 14.10.2026).
- Цикл do-while [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/do (дата обращения: 14.10.2026).
- Цикл for [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/for (дата обращения: 14.10.2026).
- Оператор break [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/break (дата обращения: 14.10.2026).
- Оператор continue [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/continue (дата обращения: 14.10.2026).
- Инкремент и декремент [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/operator_incdec (дата обращения: 14.10.2026).
- Programming: Principles and Practice Using C++, 3-е издание [Электронный ресурс]. — URL: https://www.stroustrup.com/PPP3.html (дата обращения: 14.10.2026).
- A Tour of C++, 3-е издание [Электронный ресурс]. — URL: https://www.stroustrup.com/tour3.html (дата обращения: 14.10.2026).