7.2 – Операторы if и блоки

Добавлено 23 мая 2021 в 22:11

Первая категория инструкций управления порядком выполнения программы, о которой мы поговорим, – это условные операторы. Условный оператор – это оператор, который указывает, следует ли выполнять какие-то связанные с ним инструкции.

C++ поддерживает два основных типа условных операторов: операторы if (которые мы представили в уроке «4.10 – Знакомство с операторами if», и о которых мы поговорим далее) и операторы switch (которые мы рассмотрим через пару уроков).

Краткое описание оператора if

Самый базовый тип условных операторов в C++ – это оператор if. Оператор if принимает форму:

if (условие)
    инструкция_выполняемая_если_условие_истинно;

или с необязательным оператором else:

if (условие)
    инструкция_выполняемая_если_условие_истинно;
else
    инструкция_выполняемая_если_условие_ложно;

Если условие истинно, выполняется инструкция_выполняемая_если_условие_истинно. Если условие вычисляется как ложное, и есть необязательный оператор else, выполняется инструкция_выполняемая_если_условие_ложно.

Вот простая программа, которая использует оператор if с необязательным оператором else:

#include <iostream>
 
int main()
{
    std::cout << "Enter a number: ";
    int x{};
    std::cin >> x;
 
    if (x > 10)
        std::cout << x << "is greater than 10\n";
    else
        std::cout << x << "is not greater than 10\n";
 
    return 0;
}

Эта программа работает так, как вы ожидаете:

Enter a number: 15
15 is greater than 10
Enter a number: 4
4 is not greater than 10

if или else с несколькими инструкциями

Начинающие программисты часто пробуют сделать что-то вроде этого:

#include <iostream>
 
int main()
{
    std::cout << "Enter your height (in cm): ";
    int x{};
    std::cin >> x;
 
    if (x > 140)
        std::cout << "You are tall enough to ride.\n";
    else
        std::cout << "You are not tall enough to ride.\n";
        std::cout << "Too bad!\n"; // обратите внимание на эту строку
 
    return 0;
}

Однако посмотрим, что выведет программа при запуске:

Enter your height (in cm): 180
You are tall enough to ride.
Too bad!

Эта программа работает не так, как ожидалось, потому что инструкция_выполняемая_если_условие_истинно и инструкция_выполняемая_если_условие_ложно могут быть только одной инструкцией. Отступ здесь нас обманывает – приведенная выше программа выполняется так, как если бы она была написана следующим образом:

#include <iostream>
 
int main()
{
    std::cout << "Enter your height (in cm): ";
    int x{};
    std::cin >> x;
 
    if (x > 140)
        std::cout << "You are tall enough to ride.\n";
    else
        std::cout << "You are not tall enough to ride.\n";

    std::cout << "Too bad!\n"; // обратите внимание на эту строку
 
    return 0;
}

Это проясняет, что «Too bad!» будет выводиться всегда.

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

#include <iostream>
 
int main()
{
    std::cout << "Enter your height (in cm): ";
    int x{};
    std::cin >> x;
 
    if (x > 140)
        std::cout << "You are tall enough to ride.\n";
    else
    { // обратите внимание на добавление блока здесь
        std::cout << "You are not tall enough to ride.\n";
        std::cout << "Too bad!\n";
    }
 
    return 0;
}

Помните, что блоки обрабатываются как одна инструкция, поэтому теперь всё работает как положено:

Enter your height (in cm): 180
You are tall enough to ride.
Enter your height (in cm): 130
You are not tall enough to ride.
Too bad!

Вставлять или не вставлять в блоки одиночные инструкции

В сообществе программистов ведутся споры о том, должны ли одиночные инструкции, следующие за if или else, явно заключаться в блоки или нет.

Обычно это объясняется двумя причинами. Сначала рассмотрим следующий фрагмент:

if (age >= 21)
    purchaseBeer();

Теперь предположим, что мы торопимся и изменяем эту программу, чтобы добавить еще одну способность:

if (age >= 21)
    purchaseBeer();
    gamble(); // будет выполняться всегда

К сожалению, мы разрешили несовершеннолетним играть в азартные игры. Удачи в тюрьме!

Во-вторых, это может затруднить отладку программ. Допустим, у нас есть следующий фрагмент:

if (age >= 21)
    addBeerToCart();
 
checkout();

Допустим, мы подозреваем, что с функцией addBeerToCart() что-то не так, поэтому закомментируем ее:

if (age >= 21)
//    addBeerToCart();
 
checkout();

Теперь мы сделали выполнение checkout() зависимым от условия, чего мы, конечно же, не планировали.

Ни одна из этих проблем не возникает, если вы всегда используете блоки после операторов if или else.

Лучшим аргументом в пользу отказа от использования блоков вокруг одиночных инструкций является то, что добавление блоков позволяет вам видеть по вертикали меньше кода, что делает ваш код менее читабельным и может привести к другим, более серьезным ошибкам.

Сообщество, похоже, больше поддерживает использование блоков всегда, чем их не использование, хотя эта рекомендация определенно не является повсеместной.

Лучшая практика


Рассмотрите возможность помещения одиночных инструкций, связанных с if или else, в блоки.

Альтернативный вариант – поместить одиночные инструкции в одну строку с if или else:

if (age >= 21) purchaseBeer();

Это позволяет избежать обоих упомянутых выше недостатков за небольшую плату за счет читабельности.

Неявные блоки

Если программист не объявляет блок в части инструкции оператора if или оператора else, компилятор неявно объявляет его сам. Таким образом:

if (условие)
    инструкция_выполняемая_если_условие_истинно;
else
    инструкция_выполняемая_если_условие_ложно;

фактически эквивалентно:

if (условие)
{
    инструкция_выполняемая_если_условие_истинно;
}
else
{
    инструкция_выполняемая_если_условие_ложно;
}

В большинстве случаев это не имеет значения. Однако начинающие программисты иногда пытаются сделать что-то вроде этого:

#include <iostream>
 
int main()
{
    if (true)
        int x{ 5 };
    else
        int x{ 6 };
 
    std::cout << x;
 
    return 0;
}

Это не скомпилируется, так как компилятор выдаст ошибку, что идентификатор x не определен. Это потому, что приведенный выше пример эквивалентен:

#include <iostream>
 
int main()
{
    if (true)
    {
        int x{ 5 };
    } // x уничтожается здесь
    else
    {
        int x{ 6 };
    } // x уничтожается здесь
 
    std::cout << x; // x находится вне этой области видимости
 
    return 0;
}

В этом контексте более ясно, что переменная x имеет область видимости блока и уничтожается в конце блока. К тому времени, когда мы дойдем до строки std::cout, x уже не будет существовать.

Мы продолжим изучение операторов if в следующем уроке.

Теги

C++ / CppLearnCppДля начинающихОбучениеПрограммированиеУсловный оператор

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.