Цикл (loop) — оператор, который организует повторяющееся выполнение другого
оператора. В C++ их три: while, do-while и for.
Зачем нужно
Ввести n, затем n целых чисел и найти их сумму. Для трёх или десяти чисел
можно выписать все строки руками или даже сгенерировать код скриптом. Но если
n неизвестно на этапе компиляции, без цикла не обойтись.
Как работает
while
while (<condition>) <statement>condition— выражение либо объявление переменной с инициализатором. В любом случае значение должно приводиться кbool.statement— оператор, может быть составным (блоком).
Условие проверяется перед каждой итерацией:
int n;
std::cin >> n;
int sum = 0;
while (n > 0) {
int x;
std::cin >> x;
sum += x;
--n;
}
std::cout << sum << '\n';В условии можно объявить переменную:
x = -5;
while (int sqr = x * x) {
++x;
std::cout << sqr << '\n';
}Цикл остановится, когда x дойдёт до нуля и sqr станет 0, то есть false.
Так же устроено объявление в условии if.
do-while
do <statement> while (<condition>);Тело выполняется до проверки условия, поэтому хотя бы одна итерация гарантирована. Естественный случай — читать числа до первого нуля: до первого чтения проверять нечего.
int x = 0;
int sum = 0;
do {
std::cin >> x;
sum += x;
} while (x != 0);
std::cout << sum << '\n';for
for ([init]; [condition]; [expression]) <statement>init— выражение либо объявление; область действия объявленной сущности совпадает с областью оператораfor;condition— как уwhile, пустое означаетtrue;expression— произвольное выражение, выполняется в конце итерации;statement— тело цикла.
for эквивалентен такому while:
{
[init];
while ([condition]) { // while (true), если condition пуст
<statement>
[expression];
}
}Внешние фигурные скобки — не для красоты: они и делают так, что счётчик
не виден после цикла (см. Область действия). Сравните с вариантом на
while, где int i = 0; стоит перед циклом: счётчик виден снаружи, сколько
будет итераций — неясно, а ++i легко забыть или не найти в теле. for
собирает всё это в одну строку, поэтому на практике используется чаще.
for (int i = 0; i < n; ++i) std::cout << i << '\n';
for (int i = 0; i < n; i += 2) {
std::cout << i << '\n';
}
for (std::cin >> x; x != 0; std::cin >> x) {
std::cout << x * x << '\n';
}
for (;;) ... // бесконечный цикл
for (; x;) ... // аналог while
for (int i = 0, j = 0; i < n && j < m; ++i, ++j) ...break и continue
breakдосрочно завершает весь цикл;continueдосрочно завершает текущую итерацию, цикл идёт дальше.
for (int i = 0; i < n; ++i) {
int x;
std::cin >> x;
if (x == 0) {
std::cout << "Division by zero\n";
break; // с continue — перейдёт к следующему числу
}
std::cout << y / x << '\n';
}Тонкости
- Условие входа или условие выхода?
whileиforмогут не выполнить тело ни разу, если условие ложно с самого начала.do-whileвыполнит хотя бы одну итерацию. От этого и зависит выбор. while (true) ...иfor (;;) ...— бесконечные циклы; выходят из них черезbreak.- Пустой цикл
while (x);— Неопределённое поведение, еслиxне меняет своего результата и не имеет побочных действий. - Вместо
gotoдля повторения и досрочного выхода используют циклы,breakиcontinue—gotoв курсе запрещён, см. Кодстайл курса.
Частые ошибки
- Забыть изменить переменную условия в теле
while— цикл станет бесконечным. - Ставить
;сразу послеwhile (...)илиfor (...): телом цикла станет пустой оператор. - Путать
breakиcontinue.
Углубление — АиСД L01
Сколько стоит цикл
На АиСД время работы считают в тактах — простейших действиях вроде сравнения и присвоения, см. Время работы алгоритма. Цикл стоит столько, сколько стоит его тело, умноженное на число итераций.
Проверка числа на простоту перебором всех делителей:
counter = 0 // 1 такт
for i = 1 ... p
если p ⋮ i // тело — не больше 2 тактов,
counter += 1 // выполняется N раз
если counter = 2 // 2 такта
число простое
иначе
не простоетактов, то есть — см. Асимптотические оценки. Здесь N — само число , а не длина входа.
break и оценка
Если перебирать делители от 2 до и выходить через break на первом
найденном, оценка на лекции осталась прежней: . Быстрее стало только
при переборе до : .
Не из лекции: почему break не помог
Для простого делителя нет,
breakне срабатывает, и цикл проходит все итерации. Оценку определяет такой, самый долгий случай.