User Marat Sadykov
Marat Sadykov
41 уровень

Оператор while

Статья из группы Java Developer

Введение

Наши самые первые программы представляли собой последовательность инструкций, которые выполняются одна за другой. Без развилок. Это и HelloWorld, выводящий в консоль фразу приветствия, арифметические вычисления. Оператор while - 1После первых программ мы научились ветвлению, то есть программа выполняла те или иные действия в зависимости от условий. Вот как можно было бы закодировать включение кондиционера на обогрев и охлаждение:

if (tempRoom>tempComfort)
    airConditionerOn();
if (tempRoom<tempComfort
    heaterOn();
Сделаем следующий шаг. В быту мы часто выполняем однообразные повторяющиеся действия, например, чистим яблоки для пирога. Этот увлекательный процесс можно описать как:
  1. Если в тазике есть яблоки, то выполняем шаги с 1.1 по 1.4:

    1. 1.1. Берём яблоко
    2. 1.2. Чистим и нарезаем его дольками
    3. 1.3. Помещаем на основание пирога из теста на сковороде
    4. 1.4. Возвращаемся на шаг 1.
Оператор while - 2
Допустим у вас 10 яблок, 2 руки и один нож. В жизни вы последовательно чистите весь десяток, руководствуясь одним и тем же алгоритмом. А как заставить программу делать повторяющееся действие с каждым яблоком?
  • Привяжем себя к числу яблок,но если у нас их мало – часть команд выполнялось бы вхолостую без «полезной нагрузки» (и, возможно, порезались, очищая кожуру несуществующего яблока).
  • Если яблок больше, чем наших команд обработки – часть продуктов пропала бы необработанной.
  • Подобный «код» тяжело читать, в нём много повторов, его трудно модифицировать.

Циклы – операторы многократного выполнения действий

Цикл while Java (цикл вайл) хорошо подойдёт в нашем случае. Эта конструкция оформляет многократные действия в лаконичную и понятную структуру. Алгоритм по нарезке яблок для пирога в виде while в Java мог бы выглядеть как:

while(числоЯблокВТазике>0) {
    яблоко = тазик.взятьОчередноеЯблоко();
    положитьВПирог(яблоко.чистить().нарезать());
    числоЯблокВТазике--;//-- это декремент, уменьшает количество яблок на единицу
}
System.out.println('Яблоки для пирога обработаны.');

Синтаксис команды

Первый способ описания оператора while следующий:

while(Логическое выражение) {
	// Тело цикла - периодически выполняемые оператор(ы)
}
Выполняется следующим образом (по шагам):
  1. Вычисляем Логическое условие, следующее в скобках за while.
  2. Если логическое условие истинно, то выполняются операторы в теле цикла, после выполнения последнего оператора в теле цикла, переходим на шаг 1
  3. Если логическое условие ложно, то переходим к первому оператору за пределами цикла while.

Цикл с предусловием

Так как перед выполнением тела цикла мы всегда предварительно вычисляем логическое выражение (условие входа в цикл), то этот вид while часто называют циклом с предусловием. Построим таблицу первых десяти целых, положительных степеней числа:

public static void main(String[] args) {
    int number = 3; // Возводимое в степень число
    int result = 1; // Результат возведения в степень
    int power = 1; // Начальный показатель степени
    while(power <= 10) { // условие входа в цикл
        result = result * number;
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
    }
}
Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
3 в степени 9 = 19683
3 в степени 10 = 59049
Process finished with exit code 0

Цикл с постусловием

Второй вид цикла:

do {
    // Тело цикла - периодически выполняемые оператор(ы)
}while (Логическое выражение);
Выполняется следующим образом (шаги):
  1. Выполняется тело цикла (сразу после ключевого слова do).
  2. Вычисляем Логическое условие, следующее в скобках за while.
  3. Если логическое условие истинно, то переходим на шаг 1
  4. Если логическое условие ложно, то переходим к первому оператору за пределами цикла while.
Два основных отличия от предыдущего вида цикла: тело цикла как минимум выполняется один раз и логическое условие проверяется после выполнения тела цикла. Поэтому этот вид цикла while называют циклом с постусловием. На этот раз выведем таблицу степеней числа, не превышающую 10000:

public static void main(String[] args) {
    int number = 3;// Возводимое в степень число
    int result = number;// Результат возведения в степень
    int power = 1;// Начальный показатель степени
    do {
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
        result = result * number;
    }while (result < 10000); // условие выхода из цикла
Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
Process finished with exit code 0
Обратите внимания на изменения в коде, сравнив с вариантом цикла с предусловием.

Интересные факты о работе с циклами

Управляющие команды в теле цикла

Существуют две команды, влияющие на ход выполнения цикла: break, особенности применения которого мы покажем в следующей главе, и continue.
  • continue – прекращает выполнение тела текущего цикла и осуществляет переход к логическому выражению оператора while. Если вычисленное выражение будет истинно – выполнение цикла будет продолжено.
  • break – немедленно прекращает выполнение текущего цикла и осуществляет переход к первой команде за его пределами. Таким образом, выполнение текущего цикла прерывается. Подробнее мы рассмотрим её в следующей теме.
Вспомним про наш фруктовый пример. Если мы не уверены в качестве предложенных яблок, то могли бы изменить код с применением команды continue:

while(числоЯблокВТазике>0) {
    яблоко = тазик.взятьОчередноеЯблоко();
    числоЯблокВТазике--;//-- это декремент, уменьшает количество яблок на единицу
    if (яблоко.плохое()) {  // метод вернет true для гнилого и т.п. яблока
        яблоко.выкинутьВМусор();
        continue; // продолжим цикл, перейдем к условию числоЯблокВТазике>0
    }
    положитьВПирог(яблоко.чистить().нарезать());
}
Конструкцию continue часто применяют, когда в теле цикла необходимо выполнять команды при наступлении некоторого условия, например, выполнить действия при срабатывании датчика в оборудовании (а иначе просто продолжить цикл считывания его показателей) или вычислить выражение только на определенных шагах цикла. Пример для последнего случая – вычисление в цикле while суммы кубов натуральных чисел, у которых квадрат меньше их количества:

public static void main(String[] args) {
    int sum = 0;    // итоговая сумма
    int i = 0;      // стартовое число ряда
    int count = 20; // количество чисел
    while(i<=count) {
        i++;        // берем очередное число, i++ эквивалентно i=i+1
        if (i*i<=count)  // если квадрат числа меньше
            continue;   // количества чисел - сумму не считаем
                        // переходим к следующему числу в цикле
        sum += i*i*i; // иначе считаем сумму кубов чисел
    } // sum += i*i*i - форма записи, аналогичная sum = sum + i*i*i
    System.out.println(sum);// печатаем результат
}

Бесконечный цикл

Данные управляющие команды чаще всего находят применение в бесконечном цикле. Его так называют, потому что логическое условие выхода никогда не выполняется. В коде он выглядит примерно как:

while(true) {
    // Тело цикла 
}
В этом случае и пригодится применение команды break для организации выхода из него. Этот вид цикла имеет место при ожидании внешних условий, которые формируются за пределами логики тела цикла. Например, в играх, эмулирующих виртуальный мир вокруг героя (выход из цикла = выход из игры), операционных системах. Или при использовании алгоритмов, возможно, улучшающих результат с каждым последующим вызовом в цикле, но ограничивая их по времени или наступлению внешнего события (шашки, шахматы или предсказание погоды). Следует помнить, что в обычных условиях бесконечные циклы – одна из проблем неустойчивости программы. Для демонстрации вернёмся к степеням числа:

public static void main(String[] args) {
    int number = 3; // Возводимое в степень число
    int result = 1; // Результат возведения в степень
    int power = 1; // Начальный показатель степени
    while(true) {
        result = result * number;
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
        if (power>10)
            break; // выход из цикла
    }
}
Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
3 в степени 9 = 19683
3 в степени 10 = 59049
Process finished with exit code 0

Вложенные циклы

Вот мы и подошли к завершающей теме о наших циклах. Вспомним о яблочном пироге (надеюсь, вы не голодны в данный момент) и наш «цикл»:
  1. Если в тазике есть яблоки, выполняем шаги с 1.1 по 1.4:

    1. 1.1. Берем яблоко
    2. 1.2. Чистим и нарезаем его дольками
    3. 1.3. Помещаем на основание пирога из теста на сковороде
    4. 1.4. Возвращаемся на шаг 1.
Подробнее распишем процесс нарезания дольками:
  1. Число долек = 0
  2. Пока число долек < 12, выполнить шаги с 2.1 по 2.3

    1. 2.1. Отрезать очередную дольку от яблока
    2. 2.2. Кол-во долек ++
    3. 2.3. Возвращаемся на шаг 2
И вставим в наш кондитерский алгоритм:
  1. Если в тазике есть яблоки, то выполняем шаги с 1.1 по 1.6:

    1. 1.1. Берем яблоко
    2. 1.2. Очищаем его от кожуры
    3. 1.3. Число долек = 0
    4. 1.4. Пока число долек < 12, выполнить шаги с 1.4.1 по 1.4.3
      1. 1.4.1. Отрезать очередную дольку от яблока
      2. 1.4.2. Кол-во долек ++
      3. 1.4.3. Возвращаемся на шаг 1.4
    5. 1.5. Помещаем дольки на тестовое основание пирога из теста на сковороде
    6. 1.6. Возвращаемся на шаг 1.
Получили цикл в цикле. Подобные конструкции весьма частые. Для завершающего примера построим таблицу умножения, которые школьники 90-х видели на обложках тетрадей в младших классах.
Оператор while - 3

 public static void main(String[] args) {
    // Выводим значения второго множителя в строке
    System.out.println("    2  3  4  5  6  7  8  9"); 
    int i = 2;      // первый множитель, присваиваем стартовое значение
    while(i<10) {   // Первый цикл, выполняем пока первый множитель меньше 10
        System.out.print(i + " | ");// Выводим первый множитель в начало строки
        int j = 2;                  // второй множитель, стартовое значение
        while (j<10) { // Второй цикл, выполняем пока второй множитель меньше 10
            int mul=i*j; // Считаем произведение множителей
            if (mul<10)  // Если содержит одну цифру-после него выводим два пробела
                System.out.print(mul + "  ");
            else   // иначе выводим произведение и после него - один пробел
                System.out.print(mul + " ");
            j++;     // Увеличиваем на единицу второй множитель,
        }            // Переходим к началу второго цикла (while (j<10 ).... )
        System.out.println(); // Перейдем на следующую строку вывода
        i++;                  // Увеличиваем на единицу первый множитель,
    }                         // Перейдем к началу первого цикла (while ( i<10 ) ....
}
Результат вывода на консоль:

     2  3  4  5  6  7  8  9
2 | 4 6 8 10 12 14 16 18
3 | 6 9 12 15 18 21 24 27
4 | 8 12 16 20 24 28 32 36
5 | 10 15 20 25 30 35 40 45
6 | 12 18 24 30 36 42 48 54
7 | 14 21 28 35 42 49 56 63
8 | 16 24 32 40 48 56 64 72
9 | 18 27 36 45 54 63 72 81
Process finished with exit code 0
Циклы (в частности, оператор while) – один из фундаментальных кирпичиков построения программ. Решая задачи на JavaRush, вы изучите все их разнообразие, разберёте тонкости функционирования и получите практические навыки их применения.
Комментарии (66)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Konstantin Уровень 14, Thailand
22 сентября 2021
очень крутая статья !!! спасибо!!
Dimsos Уровень 14, Краснодар, Russian Federation
13 сентября 2021
Я так понял в этом и аналогичных ему кодах ошибка. Должно быть result = power * number. Верно я понимаю? public static void main(String[] args) { int number = 3;// Возводимое в степень число int result = number;// Результат возведения в степень int power = 1;// Начальный показатель степени do { System.out.println(number + " в степени " + power + " = " + result); power++; result = result * number;
Victor #2540709 Уровень 9, Fort Lauderdale
19 июня 2021
– вычисление в цикле while суммы кубов натуральных чисел, у которых квадрат меньше их количества: Actual: while(i<=count) { i++; // берем очередное число, i++ эквивалентно i=i+1 if (i*i=<count) // если квадрат числа меньше Expected: while (i < count) { i++; // берем очередное число, i++ эквивалентно i=i+1 if (i * i < count) // если квадрат числа меньше 😎
Mike-L Уровень 43
8 июня 2021

for (int i = 1; i < 10; i++) {
    for (int j = 1; j < 10; j++) {
        System.out.print(i * j + "\t");
    }
    System.out.println();
}
используем \t и вуаля "Таблица умножения" в два захода for готова
Serbin Alexander Уровень 12, Москва, Россия
29 мая 2021
Сделал таблицу Пифагора через цикл for, с ним по проще вышло...

System.out.println("     2  3  4  5  6  7  8  9");
        for (int i = 2; i < 10; i++) {
            System.out.print(i + " | ");
            for (int j = 2; j < 10; j++) {
                int res = i * j;
                if (j < 10) {
                    System.out.print(" " + res + " ");
                } else {
                    System.out.println();
                }
            }
            System.out.println("");
Евгений Уровень 5
22 мая 2021
Ни как не мог понять в какой последовательности работает цикл в цикле. и Эта статья это не объясняет. помогло видео.
Андрей Уровень 37, Москва, Россия
7 мая 2021
Интересная статья, хотя и с небольшой ошибкой )) Для полноты не хватает описания break с метками, как раз в разделе про вложенные циклы.
Fandar Уровень 6, Санкт-Петербург, Россия
16 апреля 2021
Классная статья! Спасибо! Написать "свою" таблицу Пифагора получилось раза с 10... ))
xseiter Уровень 11, Луганск, Россия
12 апреля 2021
помню эту таблицу на своих тетрадках))))) спасибо за статью оч крутая и понятная)))))
Elina Akhmedova Уровень 0
5 апреля 2021
Огромное спасибо! Очень помогло при решении задачи по программированию😊