Циклы while / for
Во многих задачах нужно повторять одно и то же действие много раз:
перебрать числа от 1 до 100, прочитать N значений, посчитать сумму, найти максимум и т.п.
Для этого в Java есть циклы. В базовых задачах почти всегда хватает двух:
while— повторять, пока условие истинно;for— повторять фиксированное количество раз (обычно по счётчику.
Основное
Две основные формы цикла:
Чаще всего:
for— когда заранее известно количество повторений (например, ровно N чисел);while— когда повторяем «пока выполняется условие» (например, пока не встретили конец ввода или специальный знак).
Цикл while
Цикл while повторяет блок кода, пока условие истинно.
Порядок работы:
- проверяется условие
x > 0; - если условие истинно — выполняется тело цикла;
- после тела снова проверяется условие, и так далее;
- если условие стало ложным — цикл заканчивается.
Важно, чтобы внутри цикла что‑то менялось, иначе можно получить бесконечный цикл.
Цикл for
Цикл for удобно использовать, когда нужно пройти по диапазону чисел.
Здесь:
int i = 0— начальное значение счётчика;i < 5— условие продолжения цикла;i++— изменение счётчика после каждой итерации (то же, чтоi = i + 1).
В результате будут выведены числа 0, 1, 2, 3, 4.
Другой частый вариант — от 1 до N включительно:
Здесь условие i <= n, поэтому последнее число — n.
Сумма и количество
Частый шаблон: прочитать N чисел и посчитать их сумму.
int n = in.nextInt();
int sum = 0;
for (int i = 0; i < n; i++) {
int x = in.nextInt();
sum = sum + x; // или sum += x;
}
System.out.println(sum);
Здесь цикл for повторяется ровно n раз, каждый раз читается одно число.
Похожий шаблон для подсчёта количества:
int n = in.nextInt();
int countPositive = 0;
for (int i = 0; i < n; i++) {
int x = in.nextInt();
if (x > 0) {
countPositive++;
}
}
System.out.println(countPositive);
Минимум и максимум в последовательности
Ещё один стандартный приём — найти минимальное и максимальное значение.
int n = in.nextInt();
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
int x = in.nextInt();
if (x < min) {
min = x;
}
if (x > max) {
max = x;
}
}
System.out.println("min = " + min);
System.out.println("max = " + max);
Этот шаблон часто используется и для массивов.
Цикл while до конца ввода
Иногда заранее неизвестно, сколько чисел будет во входе. Тогда удобно использовать while с проверкой наличия следующего числа:
int sum = 0;
while (in.hasNextInt()) {
int x = in.nextInt();
sum = sum + x;
}
System.out.println(sum);
Цикл будет читать числа, пока во входе есть очередное целое (hasNextInt() возвращает true).
Когда числа закончатся, hasNextInt() даст false, и цикл завершится.
Что нужно запомнить
Цикл while повторяет тело, пока условие истинно:
Цикл for чаще всего используют для прохода по диапазону значений счётчику:
Для типичных задач по входным данным полезно запомнить шаблоны: сумма, количество, минимум/максимум и чтение до конца ввода.
Цикл while
В программировании часто возникает задача повторения одного и того же действия несколько раз. Для этого обычно используются циклы. Рассмотрим цикл while (пока) на примере нескольких задач.
Задача про сумму чисел от 1 до 100.
Вывести на экран все числа от 1 до 100 и их сумму.
Решение:
#include <iostream>
using namespace std;
int main()
{
int i, s;
i = 1;
s = 0;
while (i <= 100){
cout << i << " ";
s = s + i;
i = i + 1;
}
cout << s << endl;
return 0;
}
В данном примере выполняем действия внутри цикла while до тех пор, пока логическое выражение i <= 100 истинно.
Важно при написании цикла всегда изменять переменную, которая используется в условии продолжения цикла, иначе цикл будет выполняться бесконечно долго.
Задача про степень двойки.
Найдем наибольшую степень двойки, которая не превосходит 1000.
Решение:
#include <iostream>
using namespace std;
int main()
{
int ans = 1;
while (ans * 2 < 1000){
ans = ans * 2;
}
cout << ans;
return 0;
}
Заметим, что если написать в условии выхода из цикла ans < 1000, то получим первую степень двойки, большую или равную 1000.
Задача про наибольшее число в последовательности.
Дана последовательность чисел, необходимо найти самое большое число в последовательности. Признаком завершения последовательности является число 0.
Решение:
#include <iostream>
using namespace std;
int main()
{
int x, ma = 0;
cin >> x;
while (x != 0){
if (x > ma){
ma = x;
}
cin >> x;
}
cout << ma << endl;
return 0;
}
Задача про цифры числа.
Дано число x. Необходимо посчитать количество и сумму его цифр.
Решение:
#include <iostream>
using namespace std;
int main()
{
int x, cnt = 0, s = 0;
cin >> x;
while (x > 0){
cnt = cnt + 1;
s = s + x % 10;
x = x / 10;
}
cout << cnt << " " << s << endl;
return 0;
}
Заметим, что программа даст неправильный ответ для числа 0 (в его записи присутствует одна цифра). Этот случай нужно рассмотреть отдельно.
Подсчёт количества максимумов. Вечный цикл
Задача про наибольшее число в последовательности.
Дана последовательность чисел. Необходимо найти самое большое число в последовательности. Признаком завершения последовательности является число 0.
Мы уже рассматривали похожую задачу ранее, однако сейчас решим ее иначе, не опираясь на информацию о том, что заранее известны ограничения на значения чисел в последовательности.
#include <iostream>
using namespace std;
int main()
{
int maxx, now;
cin >> now;
maxx = now;
while (now > 0){
if (now > maxx){
maxx = now;
}
cin >> now;
}
cout << maxx << endl;
return 0;
}
Задача про количество максимумов в последовательности.
Дана последовательность чисел. Необходимо найти максимум в последовательности и количество элементов, значение которых равно максимуму. Признаком завершения последовательности является число 0.
#include <iostream>
using namespace std;
int main()
{
int maxx, now, cntmax = 0;
cin >> now;
maxx = now;
while (now > 0){
if (now > maxx){
maxx = now;
cntmax = 1;
} else if (now == maxx){
cntmax = cntmax + 1;
}
cin >> now;
}
cout << maxx << " " << cntmax << endl;
return 0;
}
Бесконечный цикл.
Если в реализации программы допустить ошибку, цикл может работать бесконечно долго. Рассмотрим это на примере задачи, в которой требуется вывести все числа от 1 до n.
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int i = 1;
while (i <= n){
cout << i << " ";
}
return 0;
}
Этот код бесконечно долго выводит единицы. Причина: внутри цикла не изменяется счетчик i. Добавим нужную команду и получим верное решение:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int i = 1;
while (i <= n){
cout << i << " ";
i = i + 1;
}
return 0;
}
Инструкции break и continue
Познакомимся с инструкциями break и continue.
Задача о поиске числа.
Дана последовательность и число x. Необходимо вывести номер позиции, в которой число x первый раз встречается в последовательности. Если число x не присутствует в последовательности, то необходимо вывести количество элементов в ней. Признаком завершения последовательности является число 0.
Решение.
Для решения задачи используем команду break. Эта инструкция применяется только внутри цикла. Если она запустилась, выполнение цикла немедленно останавливается, и программа переходит на первую инструкцию после цикла.
#include <iostream>
using namespace std;
int main()
{
int x, now, i = 0;
cin >> x;
cin >> now;
while (now > 0){
if (now == x){
break;
}
i = i + 1;
cin >> now;
}
cout << i;
return 0;
}
Инструкция break сильно затрудняет чтение кода, поэтому использовать ее не рекомендуется.
Задача о чётных числах.
Дана последовательность. Необходимо вывести сумму всех четных элементов последовательности. Признаком завершения последовательности является число 0.
Решение.
Для решения этой задачи будем использовать инструкцию continue. Эта инструкция применяется только внутри цикла. Если она запустилась, выполнение цикла немедленно переходит на начало следующей итерации.
#include <iostream>
using namespace std;
int main()
{
int now, summ = 0;
cin >> now;
while (now > 0){
if (now % 2 != 0){
cin >> now;
continue;
}
summ = summ + now;
cin >> now;
}
cout << summ << endl;
return 0;
}
Заметим, что в этой задаче можно написать более понятное и простое решение без инструкции continue. Инструкция continue сильно затрудняет чтение кода, поэтому использовать ее не рекомендуется.
Цикл for
Некоторые операции в языке C++ имеют сокращенную запись. Например, увеличить x на единицу можно несколькими способами:
Последние два варианта самые компактные, поэтому рекомендуем использовать именно их. Операции ++x и x++ имеют небольшое различие, но пока мы его рассматривать не будем.
Задача про числа от 1 до 100.
Выведите на экран все числа от 1 до 100.
Решение с циклом while:
Данную задачу можно решить иначе с помощью цикла for.
Решение с помощью цикла for:
Это решение лучше, так как все инструкции управления циклом находятся в одном месте, что упрощает чтение программы.
Цикл for содержит три инструкции управления, разделенные точкой с запятой:
- инициализация переменной;
- условие продолжения цикла;
- инструкция, выполняемая после завершения всех операций внутри цикла (обычно изменение счетчика).
Задача про таблицу умножения.
Выведите на экран таблицу умножения для чисел от 1 до 10.
Решение.
Решим задачу с помощью вложенного цикла for:
Иногда может быть важно не выводить пробел после последнего числа в строке. Модифицируем код, чтобы учесть это требование:
for (i = 1; i <= 10; ++i){
for (int j = 1; j <= 9; ++j){
cout << i * j << " ";
}
cout << i * 10 << endl;
}
Модифицируем программу так, чтобы не выводить перевод строки после вывода таблицы:
for (i = 1; i <= 10; ++i){
for (int j = 1; j <= 10; ++j){
cout << i * j << " ";
}
if (i != 10){
cout << endl;
}
}
Сумма чётных чисел. Цикл по нечётным числам
Задача.
Дана последовательность из n натуральных чисел. Найдите сумму четных чисел в последовательности. Значения всех чисел не превышают 2^31 - 1.
Решение.
Несмотря на то, что для хранения элементов последовательности хватит типа int, для хранения ответа необходимо использовать больший тип данных - long long.
#include <iostream>
using namespace std;
int main() {
long long sum = 0;
int now, n;
cin >> n;
for (int i = 0; i < n; ++i){
cin >> now;
if (now % 2 == 0){
sum += now;
}
}
cout << sum << endl;
return 0;
}
Задача.
Даны два натуральных числа - A и B. Необходимо вывести все нечетные числа на отрезке [A; B]. Гарантируется, что A - нечетное и A < B.
Решение.
#include <iostream>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
for (int i = a; i <= b; i += 2){
cout << i << " ";
}
return 0;
}
Преинкремент и постинкремент
Разберем различия инструкций преинкремента (++i) и постинкремента (i++).
Приведем два примера:
На экран будет выведено два числа - 10 и 11.
На экран будет выведено два числа - 11 и 11.
Таким образом, преинкремент сначала прибавляет единицу к переменной b, а затем возвращает ее значение. Постинкремент, наоборот, сначала возвращает значение переменной b, а затем прибавляет к ней единицу.
Такое поведение называется побочным эффектом операций и часто позволяет сократить длину кода. Однако мы не рекомендуем пользоваться этим приемом, так как это может привести к ошибкам в программе и усложнить чтение кода. Советуем не использовать преинкремент и постинкремент в присваиваниях.
Цикл по всем n-значным числам
Задача.
Выведите все n-значные натуральные числа.
Решение.
#include <iostream>
using namespace std;
int main()
{
int d;
cin >> d;
int mind = 1, maxd;
for (int i = 1; i < d ; ++i){
mind *= 10;
}
maxd = mind * 10 - 1;
for (int i = mind; i <= maxd; ++i){
cout << i << " ";
}
return 0;
}
Цикл по числам, делящимся на заданное число
Задача.
Даны три натуральных числа - a, b, c. Выведите все числа на отрезке [a; b], делящиеся на c.
Решение.
#include <iostream>
using namespace std;
int main()
{
int a, b, c;
cin >> a >> b >> c;
int m = a % c;
if (m != 0){
a += c - m;
}
for (int i = a; i <= b; i += c){
cout << i << " ";
}
cout << endl;
return 0;
}
Заметим, что в данной программе несложно избавиться от условной инструкции. Для этого нужно придумать формулу для вычисления нового значения переменной a перед циклом с помощью арифметических операций. Оставим это для самостоятельного упражнения.
По материалам:
М. Густокашин. Введение в программирование на языке C++. Сириус Курсы. Перейти к курсу.
В Python есть while и for, но for чаще используют для прохода по диапазону или по элементам.
while— выполнять, пока условие истинно.for— пройти по последовательности (например, поrange(...)).
Форма while
Форма for по range
Пример: отсчёт назад
Пример: сумма N чисел
Пример: чтение до конца ввода
Запись цикла for
В Java и C++ for состоит из трёх частей: инициализация, условие, шаг. В Python for обычно проходит по range(...) или по элементам, а шаг и границы задаются в range.
Границы диапазона
Java/C++ часто пишут i < n, и тогда значения идут 0, 1, ..., n-1. В Python это ровно так же работает с range(n).
Скобки и отступы
В Java и C++ тело цикла обычно выделяют фигурными скобками { ... }. В Python тело цикла задаётся отступами.