Циклы. for, while, вложенные циклы
Цикл while и счётчик, поиск минимума и суммы последовательности, цифры числа, цикл for и do-while, вложенные циклы, break и continue, отладка и вечный цикл.
Ветвление позволило программе выбрать одно из продолжений. Цикл позволяет выполнить одни и те же действия много раз — и это первая конструкция, с которой программа может обработать данные, объём которых заранее неизвестен. Заодно появляется новая неприятность: цикл может не закончиться никогда.
Цикл while
«While» переводится как «пока» и в программировании означает «пока условие верно, нужно выполнять следующие действия». В жизни цикл «пока» встречается очень часто. Например, вам срочно понадобились фиолетовые кроссовки для вечеринки. Как описать ваши действия? «Пока не найдёшь фиолетовые кроссовки — ходи по магазинам. Как только найдёшь — покупай».
while очень похож на if, но если if выполняет действия один раз,
то while будет делать их до тех пор, пока выполнено условие.
Рассмотрим цикл на примере. Есть число N; нужно вывести все числа
по возрастанию от 1 до N. Заведём счётчик — переменную i, равную текущему
числу. Вначале это единица. Пока значение счётчика не превысит N, выводим
его текущее значение и каждый раз увеличиваем на единицу:
int i, n;
cin >> n;
i = 1;
while (i <= n) {
cout << i << " ";
i = i + 1;
}
cout << endl;Когда выполнение доходит до закрывающей фигурной скобки, происходит возврат
к строке с while и повторная проверка условия. Если оно верно, блок команд
выполняется ещё раз; если нет — программа продолжается с команд после блока.
У любого цикла со счётчиком три обязательные части, и забыть можно любую:
- начальное значение счётчика — до цикла (
i = 1); - условие продолжения — в заголовке (
i <= n); - изменение счётчика — в теле (
i = i + 1).
Попробуйте ввести 0 и объяснить результат: условие ложно с самого начала,
и тело цикла не выполняется ни разу. Это нормальное и частое поведение while.
Поиск минимума последовательности
Компания друзей хочет купить пиццу. Чтобы не платить за доставку, нужно послать кого-нибудь в пиццерию. Кого? Самого младшего. Формально: среди последовательности чисел нужно найти и вывести минимальное. Последовательность состоит из положительных чисел и оканчивается нулём.
Как такую задачу будет решать человек? Каждый раз, когда ему называют число, он сравнивает его с тем минимумом, который встречался раньше, и, если новое число ещё меньше, запоминает его. Так продолжается, пока числа не закончатся. Вначале нужно запомнить самое первое названное число, в конце — назвать запомненное.
int min, now;
cin >> now;
min = now;
while (now != 0) {
if (now < min) {
min = now;
}
cin >> now;
}
cout << min << endl;Разберите два места, в которых легко ошибиться. Первое: min = now до цикла.
Начать с нуля нельзя — тогда ноль и окажется минимумом; начать с «очень большого
числа» можно, но первый элемент для этого подходит лучше. Второе: чтение
следующего числа — последняя команда тела. Если поставить его первым, первое
число прочитается дважды.
Сумма последовательности
Те же друзья решили посчитать, хватит ли у них денег: каждый говорит, сколько у него есть. Последовательность из положительных чисел оканчивается нулём, нужно вывести сумму всех элементов.
Задача решается так же, как человеком: достаточно помнить сумму уже названных чисел и каждое следующее просто прибавлять. Сначала нужно запомнить ноль — числа ещё не заданы.
int sum = 0, now;
cin >> now;
while (now != 0) {
sum = sum + now;
cin >> now;
}
cout << sum << endl;Сравните с предыдущей задачей: структура цикла та же, различаются только
начальное значение (0 против первого элемента) и действие в теле.
Это общий шаблон «накопитель», и он же сработает для произведения,
количества подходящих элементов или максимума.
Цифры числа
Задачи на подсчёт суммы, минимумов и максимумов встречаются очень часто. Например, задача о счастливом билетике: если сумма цифр в первой половине номера совпадает с суммой цифр во второй половине, билет считается счастливым (и его нужно съесть).
Мы уже знаем, как узнать последнюю цифру числа — остаток от деления на 10, — и как отбросить её: поделить число на 10 нацело. Значит, можно поочерёдно рассмотреть все цифры справа налево и остановиться, когда цифры закончатся (число станет равным нулю). Сумму считаем накопителем, и делаем это для каждой половины номера:
int part1, part2;
cin >> part1 >> part2;
int sum1 = 0, sum2 = 0;
while (part1 != 0) {
sum1 = sum1 + part1 % 10;
part1 = part1 / 10;
}
while (part2 != 0) {
sum2 = sum2 + part2 % 10;
part2 = part2 / 10;
}
if (sum1 == sum2) {
cout << "Lucky ticket";
} else {
cout << "unlucky :(";
}
cout << endl;Обратите внимание: условие цикла здесь не счётчик, а сама обрабатываемая
величина. Число уменьшается на каждом шаге и гарантированно дойдёт до нуля.
Проверьте на 123 321 и на 123 124.
Цикл for
В цикле со счётчиком три части — начальное значение, условие и изменение —
разбросаны по трём разным местам программы, и любую из них легко потерять.
Цикл for собирает их в одну строку:
for (начальное значение; условие; изменение) {
// тело цикла
}Та же задача о выводе чисел от 1 до N:
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cout << i << " ";
}
cout << endl;Порядок работы: один раз выполняется начальное значение, затем проверяется
условие, затем тело, затем изменение, затем снова условие — и так далее.
for и while взаимозаменяемы: любой for переписывается в while
и наоборот.
Когда что выбирать: for — когда число повторений известно («для каждого
элемента», «десять раз»), while — когда неизвестно («пока не встретится
ноль», «пока не найдём»). Технической разницы нет, но правильно выбранный
цикл сам объясняет читателю, что происходит.
Ещё одно практическое отличие: int i объявлена внутри for, и после цикла
её не существует. Это хорошо — счётчик не мешается дальше в программе, — но если
значение счётчика нужно после цикла, переменную придётся объявить до него.
Цикл do…while
Третья форма: условие проверяется после тела, поэтому тело выполняется хотя бы один раз.
int n;
do {
cin >> n;
cout << "прочитано " << n << endl;
} while (n <= 0);
cout << "принято: " << n << endl;Это типичное применение do…while: проверка введённого значения. Прочитать
число надо до того, как его можно проверить, поэтому условие и оказывается внизу.
Тот же алгоритм на while потребовал бы читать число дважды — до цикла
и в конце тела, — и это ровно та дубликация, от которой избавляет do…while.
Обратите внимание на точку с запятой после while (n <= 0); — она обязательна.
Вложенные циклы
Тело цикла — обычный блок команд, и в нём может находиться другой цикл. Тогда внутренний цикл полностью прокручивается на каждом шаге внешнего. Классический пример — таблица умножения:
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 5; j++) {
cout << setw(4) << i * j;
}
cout << endl;
}Внешний цикл отвечает за строки, внутренний — за столбцы внутри строки,
а cout << endl стоит между циклами: после каждой строки, но не после
каждого числа. Манипулятор setw(4) из <iomanip> выравнивает столбцы,
отводя каждому числу четыре позиции.
Число шагов у вложенных циклов перемножается: 5 × 5 — это 25 выполнений
внутреннего тела. Поменяйте границы на 100 и 100 — будет уже десять тысяч,
и это стоит помнить, когда внутри цикла происходит что-то тяжёлое.
Второй важный момент — у каждого цикла свой счётчик. Если внутренний цикл
использует тот же i, что и внешний, программа сломается самым запутанным
способом: внешний цикл получит изменённый счётчик.
Инструкции break и continue
Для управления поведением цикла есть две инструкции, которые позволяют досрочно прерывать выполнение цикла или начинать выполнение его тела сначала.
break прекращает работу цикла — как будто не было выполнено условие.
Осмысленное использование break возможно только внутри if внутри цикла.
Использование break — плохой тон, по возможности следует обходиться без него.
Пример ниже — именно пример, так писать не нужно:
int i;
i = 1;
while (1) {
cout << i;
i = i + 1;
if (i > 100)
break;
}
cout << endl;Условие while (1) — всегда истина, то есть цикл сам по себе бесконечный,
и единственный выход из него — break. Сравните с обычной записью
while (i <= 100): она делает то же самое, но условие окончания видно
в заголовке, а не спрятано в середине тела. Именно поэтому break считают
плохим тоном: он прячет условие выхода.
continue начинает исполнение тела цикла заново, начиная с проверки условия.
Её нужно использовать, если начиная с какого-то места в теле и при выполнении
каких-то условий дальнейшие действия нежелательны. В задаче о кроссовках это
выглядело бы так: если в магазине очередь в сто человек, сразу идём
в следующий — независимо от того, есть ли в этом магазине кроссовки.
Дана последовательность чисел, оканчивающаяся нулём; нужно вывести все
положительные числа из неё (при решении этой задачи можно и нужно обходиться
без continue, но для примера):
int now;
now = -1;
while (now != 0) {
cin >> now;
if (now <= 0)
continue;
cout << now << " ";
}
cout << endl;В этом решении есть интересный момент: перед циклом переменная инициализируется
заведомо подходящим значением — иначе первая же проверка условия читала бы мусор.
Команда вывода выполняется только в том случае, если не выполнится условие в if.
`continue` в цикле `for` и в цикле `while` ведут себя по-разному
В for при continue изменение счётчика всё равно выполняется — оно записано
в заголовке. В while изменение счётчика находится в теле, и continue его
пропускает. Забытый счётчик перед continue — самый частый способ
случайно получить вечный цикл.
Вечный цикл
С помощью while очень легко сделать вечный цикл: достаточно написать условие,
которое никогда не будет нарушено. Возьмём задачу о выводе всех чисел
от 1 до 100 и забудем об увеличении счётчика:
int i;
i = 1;
while (i <= 100) {
cout << i << " ";
}Эта программа будет работать вечно, потому что счётчик всегда будет равен единице. Этот фрагмент не сделан запускаемым намеренно — запустить его здесь нельзя: страница ждала бы результата, которого не будет.
Как прервать зациклившуюся программу
В среде разработки: в Visual Studio — Shift+F5, в Code::Blocks и VS Code —
кнопка остановки в панели запуска. В терминале — Ctrl+C. Закрывать чёрное
окно консоли крестиком не стоит: программа может остаться в памяти.
На этой странице всё проще: у запускаемых примеров есть ограничение по времени, и зациклившийся пример остановится сам с сообщением о превышении времени. Попробуйте: впишите бесконечный цикл в любой пример выше.
Отладка программ
Мы дошли до достаточно сложных программ, и находить в них ошибку методом пристального взгляда бывает непросто. Для облегчения поиска ошибок есть средства отладки.
Основной инструмент — точка остановки (breakpoint). Она ставится на строке, перед выполнением которой программу нужно остановить. Когда выполнение доходит до точки остановки, оно прерывается, и можно посмотреть текущие значения всех переменных: обычно достаточно навести курсор на имя переменной в коде.
Дальше есть два способа продолжить: до следующей точки остановки
или пошагово, строка за строкой. Во второй режиме выполняется одна
выделенная строка, и происходит переход к следующей команде. В Visual Studio
это F5 и F10; в других средах клавиши свои, но режимы те же.
Чаще всего отладка состоит в том, чтобы поставить точку остановки в начале потенциально ошибочного кода, запустить программу, проверить, что всё считалось правильно, а затем выполнять программу пошагово, смотреть на значения переменных и ловить момент, когда что-то пойдёт не так.
На этой странице отладчика нет
Примеры на сайте запускаются целиком: есть код, ввод и вывод, точку остановки
поставить некуда. Это ограничение браузерного запуска, и обходится оно
единственным способом — выводом на печать: добавьте cout внутрь цикла
и напечатайте значения переменных на каждом шаге.
Приём кажется примитивным, но работает везде, не требует настройки и остаётся
основным инструментом отладки у очень многих. Попробуйте на примере с поиском
минимума: напечатайте now и min в начале каждого шага и посмотрите,
как минимум обновляется.
Задание к лабораторной
Рабочая программа не даёт отдельных вариантов по циклам, поэтому задания ниже составлены к этому уроку.
Вариант 1. Программа читает целое число n и печатает: сумму всех чисел
от 1 до n, их произведение и количество чётных среди них. Все три величины
считаются в одном цикле. В отчёте укажите, при каком n произведение
перестаёт помещаться в int, и как это проявляется.
Вариант 2. Программа читает последовательность целых чисел, оканчивающуюся нулём, и печатает: количество чисел, их сумму, минимум, максимум и среднее арифметическое. Предусмотрите случай, когда первое же введённое число — ноль (последовательность пуста).
Вариант 3. Программа читает натуральное число и печатает: количество его
цифр, сумму цифр, число, записанное теми же цифрами в обратном порядке,
и является ли число палиндромом. Используйте только цикл и операции % и /,
без строк и массивов.
Вариант 4. Программа печатает таблицу умножения от a до b
(границы вводятся) вложенными циклами, с выравниванием столбцов
и подписанной первой строкой. Проверьте случай a > b.
Вариант 5. Программа читает целое число и определяет, простое ли оно, перебором возможных делителей в цикле. Определите, до какого предела достаточно проверять делители, и обоснуйте это в отчёте.
Как оценивается лабораторная
Работа сдаётся преподавателю очно: сайт её не принимает и не оценивает. Шкала и показатели ниже — из рабочей программы дисциплины, раздел 7.
Показатели оценки
- степень соответствия выполненного задания поставленным целям, задачам и требованиям;
- оформление, структурирование и комментирование лабораторной работы;
- уникальность выполнения работы (отличие от работ коллег);
- успешные ответы на контрольные вопросы.
Баллы
- 86–100отлично— оформление соответствует требованиям, критерии выдержаны, защита всего перечня контрольных вопросов.
- 66–85хорошо— оформление соответствует требованиям, критерии выдержаны, защита только до 85 % контрольных вопросов.
- 51–65удовлетворительно— оформление соответствует требованиям, критерии выдержаны, защита только до 51 % контрольных вопросов.
- 0–50неудовлетворительно— оформление не соответствует требованиям, критерии не выдержаны, защита менее 51 % контрольных вопросов.
Проверьте себя
Викторина по теме
Тело цикла while может не выполниться ни разу.
Ссылки на литературу
- Воробьев, Г. А. Основы программирования на C++ : учебно-методическое пособие. — Липецк : Липецкий ГПУ, 2022. — 89 с. — ISBN 978-5-907461-84-0. Лань : электронно-библиотечная система (дата обращения: 15.01.2026). Доступ: для авторизованных пользователей
- Калитвин, В. А. Введение в программирование на C++ : учебное пособие. — Липецк : Липецкий ГПУ, 2023. — 84 с. — ISBN 978-5-907655-86-7. Лань : электронно-библиотечная система (дата обращения: 15.01.2026). Доступ: для авторизованных пользователей
- Широбокова, С. Н., Кацупеев, А. А., Сулыз, А. В. Программирование на языке C++ для лабораторных занятий : учебное пособие. — Новочеркасск : ЮРГПУ, 2020. — 104 с. — ISBN 978-5-9997-0725-3. Лань : электронно-библиотечная система (дата обращения: 15.01.2026). Доступ: для авторизованных пользователей