Перейти к содержимому
Теория · Циклы · урок 3 из 8

Цикл for

В цикле while из прошлого урока номер круга жил в трёх разных местах: переменную объявляли до цикла, проверяли в условии и меняли в конце тела. Стоит ошибиться в одном из трёх мест — и цикл не начнётся или не закончится.

У бегуна те же три дела. Перед стартом он один раз выставляет на табло 1. Перед каждым кругом смотрит на табло. После каждого круга прибавляет к номеру единицу.

Цикл for собирает все три дела в одну строку. Вот программа, которая складывает числа от 1 до 100:

JAVA
public class Main {
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
        }
        System.out.println(sum); // 5050
    }
}

Давайте разберём её по строкам:

  1. int sum = 0; заводит сумму.
  2. for (int i = 1; i <= 100; i++) повторяет тело для i от 1 до 100.
  3. sum += i; прибавляет к сумме очередное i. Для int эта запись делает то же, что sum = sum + i, только короче.
  4. System.out.println(sum) выполняется после цикла и печатает 5050.

Три части заголовка

Строку for (int i = 1; i <= 100; i++) называют заголовком цикла. В круглых скобках три части, разделённые точкой с запятой:

  • int i = 1 — инициализация: выполняется один раз, до первой итерации. Бегун выставляет на табло 1.
  • i <= 100 — условие: проверяется перед каждой итерацией, как в while. Бегун смотрит на табло.
  • i++ — шаг: выполняется после тела, перед следующей проверкой. Бегун прибавляет к номеру единицу.

Заголовок читается слева направо, но выполняется в другом порядке:

  1. Инициализация — один раз.
  2. Условие. Если оно ложно, цикл заканчивается.
  3. Тело.
  4. Шаг, и снова пункт 2.

Шаг записан в заголовке перед телом, а выполняется после него. Про этот порядок любят спрашивать на собеседованиях. В виджете тот же цикл, только до 3: нажимайте «Следующий шаг» и следите, какая часть заголовка выполняется сейчас.

ВживуюПорядок частей forшаг 1 из 13 · рамок: 1

int sum = 0 заводит сумму.

Следите, какая часть заголовка выполняется на каждом шаге

Когда виджет дошёл до println, переменной i уже нет. Её объявили прямо в заголовке, и живёт она только внутри цикла.

Здесь картинка со стадионом расходится с Java. Табло на стадионе остаётся и после забега, а переменной из заголовка for после цикла не существует.

Другие формы заголовка

Шаг не обязан прибавлять единицу. -- вычитает единицу, а += прибавляет любое число:

  • for (int i = 0; i < 5; i++) — пять итераций, i от 0 до 4;
  • for (int i = 3; i >= 1; i--) — обратный отсчёт: 3, 2, 1;
  • for (int i = 0; i <= 10; i += 2) — чётные числа от 0 до 10.

i++ и ++i

Оператор ++ прибавляет к переменной единицу. Его называют инкрементом, и у него две формы. Отдельной инструкцией, как в шаге цикла, они работают одинаково. Разница появляется, когда значение ++ идёт дальше: в печать, в присваивание, в другое выражение.

JAVA
int n = 3;
System.out.println(n++); // 3
System.out.println(n);   // 4
System.out.println(++n); // 5
System.out.println(n);   // 5

Постфиксная форма n++

++ стоит после имени. Выражение n++ даёт старое значение переменной, а единицу прибавляет уже потом. Поэтому первая строка печатает 3, хотя после неё n равна 4: это показывает вторая строка.

Префиксная форма ++n

++ стоит перед именем. Выражение ++n сначала прибавляет единицу, а потом даёт новое значение. Третья строка увеличивает n с 4 до 5 и печатает 5.

Запомнить помогает порядок записи: что стоит первым, то и происходит первым. В n++ первым стоит имя — сначала берётся значение. В ++n первым стоит ++ — сначала прибавляется единица. С -- всё так же: n-- даёт старое значение, --n — новое.

Эту разницу часто проверяют на собеседованиях: показывают короткую программу с i++ и ++i и спрашивают, что она напечатает. В своём коде, чтобы не путаться, пишите ++ отдельной инструкцией, а не внутри другого выражения.

Частая ошибка

Значение i понадобилось после цикла:

JAVA
for (int i = 1; i <= 3; i++) {
    System.out.print(i + " ");
}
System.out.println(i); // ✗
TEXT
error: cannot find symbol

Компилятор не знает имени i в последней строке: переменная из заголовка исчезла вместе с циклом. Сообщение то же, что для переменной, которую забыли объявить. Если значение нужно после цикла, храните его в переменной, объявленной до цикла, как sum в первом примере.

Главное

  • Инициализация for выполняется один раз, условие — перед каждой итерацией, шаг — после тела.
  • n++ даёт старое значение и потом прибавляет единицу, а ++n прибавляет единицу и даёт новое значение.
  • Отдельной инструкцией i++ и ++i работают одинаково.
  • Переменная, объявленная в заголовке for, существует только внутри цикла.