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, ви вивчите все їхнє розмаїття, розберете тонкощі функціонування та отримаєте практичні навички їхнього застосування.
Коментарі
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Для цієї сторінки немає коментарів.