JavaRush /Java блог /Java Developer /Цикл While у Java
Автор
Артем Divertitto
Senior Android-разработчик в United Tech

Цикл While у Java

Стаття з групи 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
Процес завершився з кодом виходу 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
Процес завершився з кодом виходу 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
Процес завершився з кодом виходу 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-х бачили на обкладинках зошитів у молодших класах.

 public static void main(String[] args) {
    // Виводимо значення другого множника в рядку
    System.out.println(" 2 3 4 5 6 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, ви вивчите все їхнє розмаїття, розберете тонкощі функціонування та отримаєте практичні навички їхнього застосування.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ