JavaRush /Курси /C++ SELF /Умовний оператор: if/else

Умовний оператор: if/else

C++ SELF
Рівень 3 , Лекція 2
Відкрита

1. Синтаксис розгалужень: if, else, else if

Коли ви лише починаєте програмувати, може здаватися, що програма — це просто калькулятор: ввели числа, отримали відповідь. Але доволі швидко зʼясовується: реальна програма майже завжди розгалужується. Якщо користувач увів одне — робимо так, якщо інше — інакше. Навіть у стандарті C++ окремо виділяють поняття condition («умова») як важливу частину керувальних конструкцій на кшталт if.

Головна думка проста: if — це роздоріжжя. Умова — це запитання, на яке програма відповідає true або false, а потім обирає одну з гілок.

Перш ніж писати «розумні» умови, важливо добре зрозуміти основу: if — це не магія, а дуже строга конструкція. У дужках після if має бути вираз типу bool або те, що до нього зводиться. Далі йде команда або блок команд. Саме тут новачки вперше по-справжньому стикаються із синтаксисом: де потрібні круглі дужки, де — фігурні, і чому одна зайва крапка з комою ; повністю змінює зміст.

Базовий if: «якщо (…) то …»

Мінімальний шаблон має такий вигляд:

if (condition) {
    // дії, якщо condition == true
}
Базова форма if

Приклад: «повнолітній чи ні»

Почнімо з найпростішого: зчитаємо вік і виведемо статус.

#include <iostream>

int main() {
    int age = 0;
    std::cin >> age;

    if (age >= 18) {
        std::cout << "adult\n"; // наприклад, при введенні 18 -> adult
    }
}

Тут важливо зрозуміти: age >= 18 — це вираз, який обчислюється до true або false. Якщо результат — true, виконується блок.

else: «інакше робимо ось що»

Якщо if — це «якщо правда», то else — це «якщо неправда». Він завжди належить до найближчого if, у якого немає власного else. Це важливий момент: відступи й {} справді рятують нерви.

Базова форма:

if (condition) {
    // true-гілка
} else {
    // false-гілка
}
Повне розгалуження if / else

Це вже повноцінне розгалуження: «ліворуч» або «праворуч».

else if: «інакше якщо … інакше якщо … інакше …»

Тепер переходимо до ситуації, коли треба вибрати одну гілку з кількох. Таке трапляється дуже часто: число може бути додатним, відʼємним або нулем; команда може бути "add", "remove" чи "exit"; оцінка може бути «відмінно», «добре», «задовільно» або «погано».

Ланцюжок має такий вигляд:

if (cond1) {
    ...
} else if (cond2) {
    ...
} else if (cond3) {
    ...
} else {
    ...
}

Ключове правило: у такому ланцюжку виконується рівно одна гілка — перша, чия умова спрацювала, якщо рухатися згори донизу.

Приклад: знак числа

#include <iostream>

int main() {
    int x = 0;
    std::cin >> x;

    if (x > 0) {
        std::cout << "positive\n"; // 5 -> positive
    } else if (x < 0) {
        std::cout << "negative\n"; // -3 -> negative
    } else {
        std::cout << "zero\n";     // 0 -> zero
    }
}

Чому порядок важливий? Тому що перевірки виконуються згори донизу. Якби ми помилково написали x >= 0 першою умовою, усе, що не є відʼємним, уже «поглинула» б перша перевірка.

2. Читабельність розгалужень: {}, смислові рівні та назви перевірок

Є два типи новачків: ті, хто завжди ставить {}, і ті, хто одного разу втратив дві години через пропущені {}, — а потім теж почав ставити їх завжди.

Формально C++ дозволяє писати так:

if (condition)
    std::cout << "Hello\n";

Але для початківця це як їздити на велосипеді без рук: дехто вміє, та ми ж поки вчимося їздити, а не вражати перехожих.

Чому «один рядок без {}» небезпечний

Проблема зʼявляється, коли ви спершу написали один рядок, а потім додали другий і забули про дужки. Код компілюється, але поводиться дивно.

Порівняйте:

// ПОГАНО: легко зламати при додаванні рядків
if (age >= 18)
    std::cout << "adult\n";
    std::cout << "welcome!\n"; // виконується ЗАВЖДИ

і

// ДОБРЕ: структура завжди очевидна
if (age >= 18) {
    std::cout << "adult\n";
    std::cout << "welcome!\n";
}

Друга версія своїм виглядом буквально підказує: «ці два рядки — одна дія в межах цієї гілки».

else if і вкладений if: це різні смисли

Дуже поширене запитання: «А можна я просто вкладу if усередину if?» Можна. Але зміст буде іншим. А якщо зміст інший, краще писати так, щоб читач — зокрема й ви самі за тиждень — побачив це відразу.

else if — це «вибір однієї гілки з набору взаємовиключних варіантів».

Вкладений if — це «ми вже вибрали гілку і всередині неї щось уточнюємо».

Приклад: де потрібен вкладений if

Припустімо, спочатку ми перевіряємо, чи вік узагалі коректний, тобто чи не є він відʼємним. І лише потім вирішуємо: adult чи minor.

#include <iostream>

int main() {
    int age = 0;
    std::cin >> age;

    if (age < 0) {
        std::cout << "invalid\n";      // -5 -> invalid
    } else {
        if (age >= 18) {
            std::cout << "adult\n";    // 20 -> adult
        } else {
            std::cout << "minor\n";    // 7 -> minor
        }
    }
}

Зміст тут такий: якщо вік некоректний — одразу invalid. Інакше визначаємо, чи людина повнолітня.

Якщо спробувати вмістити це в один ланцюжок else if, теж можна отримати робочий варіант. Але новачкові такий запис зазвичай важче читати, бо в ньому змішуються різні смислові рівні: спочатку перевірка коректності даних, а потім їх класифікація.

Робіть умови читабельними: називайте перевірки

У цій лекції ми говоримо не лише про те, як працює if, а й про те, як зробити так, щоб ваш код не скидався на шифр. Один із найпростіших прийомів — винести частину перевірки в змінну типу bool зі зрозумілою назвою.

Це не «зайві змінні», а радше підписи на дротах. Без підпису теж можна підʼєднати, але потім ремонтувати значно болючіше.

#include <iostream>

int main() {
    int age = 0;
    std::cin >> age;

    bool is_adult = (age >= 18);

    if (is_adult) {
        std::cout << "adult\n";
    } else {
        std::cout << "minor\n";
    }
}

Перевага такого підходу в тому, що умова if (is_adult) читається майже як англійське речення. Недолік лише один: треба дібрати вдалу назву. Але це складно тільки спочатку — згодом мозок робить так майже автоматично.

3. Практичний мініприклад: «обробник команди» без циклів

Зараз ми зберемо невелику заготовку застосунку, яка далі розвиватиметься протягом курсу. Поки що — без циклів, бо їх ми ще не проходили. Тому програма обробить одну команду й завершиться. Але навіть у такому вигляді вона вже схожа на реальний консольний інтерфейс: користувач вводить команду, а програма вирішує, що робити далі.

Ідея проста: зчитуємо рядок cmd і виконуємо різні дії.

Версія 1: три команди

#include <iostream>
#include <string>

int main() {
    std::string cmd;
    std::cin >> cmd;

    if (cmd == "hello") {
        std::cout << "Hello!\n";           // hello -> Hello!
    } else if (cmd == "help") {
        std::cout << "Commands: hello, help, exit\n";
    } else if (cmd == "exit") {
        std::cout << "Bye!\n";             // exit -> Bye!
    } else {
        std::cout << "Unknown command\n";  // qwerty -> Unknown command
    }
}

Зауважте, як легко це читається: згори донизу — майже як список правил. Саме тому ланцюжок else if такий популярний на ранніх етапах навчання.

Версія 2: команда з числом

Нехай командою буде "age", а після неї користувач введе число. Поки що не додаємо складних перевірок введення — до цього ще повернемося. Зате тут добре видно, як гілка if може містити власний невеликий сценарій.

#include <iostream>
#include <string>

int main() {
    std::string cmd;
    std::cin >> cmd;

    if (cmd == "age") {
        int age = 0;
        std::cin >> age;

        if (age >= 18) {
            std::cout << "adult\n"; // age 20 -> adult
        } else {
            std::cout << "minor\n"; // age 7 -> minor
        }
    } else {
        std::cout << "Try command: age\n";
    }
}

Зверніть увагу: усередині гілки cmd == "age" ми робимо ще одне розгалуження. Це цілком життєва ситуація: спочатку обираємо режим, а вже в ньому — конкретну дію.

Невелика схема: як виконується if / else if / else

Іноді корисно побачити else if не як «магічні слова», а як простий алгоритм: перевірили перше — якщо так, виконали й вийшли; якщо ні — пішли далі.

flowchart TD
    A[Початок] --> B{cond1?}
    B -->|так| C[гілка 1]
    B -->|ні| D{cond2?}
    D -->|так| E[гілка 2]
    D -->|ні| F{cond3?}
    F -->|так| G[гілка 3]
    F -->|ні| H[гілка else]
    C --> Z[Кінець]
    E --> Z
    G --> Z
    H --> Z

Ця схема корисна тим, що наочно показує головний факт: виконується лише одна гілка, а перевірки йдуть згори донизу.

4. Типові помилки під час роботи з if/else

Помилка № 1: крапка з комою після if.
Новачки інколи пишуть if (cond); — і це виглядає майже правильно, але зміст ламається повністю. Крапка з комою тут означає «порожню команду»: умову перевірили, а далі нічого не зробили. Блок після цього виконується вже як звичайний блок, тобто майже завжди. Якщо бачите дивну поведінку на кшталт «гілка виконується завжди», насамперед шукайте зайвий ;.

Помилка № 2: гілки без {} і «рядок, що втік».
Спочатку все працює: у гілці лише один рядок. Потім ви додаєте другий, але забуваєте про фігурні дужки, і цей другий рядок починає виконуватися завжди або не тоді, коли треба. Це одна з найприкріших помилок: компілятор не свариться, а логіка вже інша. Звичка «завжди ставити {}» майже повністю від цього захищає.

Помилка № 3: переплутали зміст else if і вкладеного if.
Якщо вам потрібно вибрати «один варіант із багатьох», використовуйте ланцюжок else if. Якщо ж потрібно «спочатку перевірити одне, а всередині вже уточнити інше», використовуйте вкладений if. Коли ці два смислові рівні змішуються, код стає важким для читання: наче працює, але не дуже зрозуміло, що саме автор хотів сказати.

Помилка № 4: невдалий порядок перевірок у ланцюжку else if.
Проблема зʼявляється, коли перша перевірка надто широка й перехоплює випадки, які мали б потрапити в нижні гілки. Наприклад, if (x >= 0) перед else if (x == 0) — і гілка x == 0 ніколи не виконається. Виправлення просте: спочатку ставимо специфічніші випадки, потім — загальніші. Або спершу проговорюємо словами «драбину» перевірок, а вже потім записуємо її в код.

Помилка № 5: довгі гілки та «втрата змісту».
Іноді початківець пише в кожній гілці по 40 рядків. Формально це нормально, але читати такий код важко: поки дійдете до кінця, уже легко забути, яка саме умова привела вас у цю гілку. На цьому етапі курсу ми ще не розбираємо функції, тому рецепт простий: тримайте гілки короткими, виводьте зрозумілі повідомлення, а умови формулюйте максимально ясно. Коли дійдемо до функцій, навчимося розвантажувати main. А поки що тренуймо охайний стиль просто тут.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ