Операторы принятия решений в C++: if и switch

User Rating: 5 / 5

В языке C++ как и во многих других языках программирования поддерживаются операторы принятия решений. К ним относятся два основных оператора C++: if и switch, каждый из которых мы рассмотрим в данной статье.

Что мы здесь понимаем под принятием решений? Все люди для достижения каких-то результатов или эффектов принимают определённые решения в течение дня (да и всей нашей жизни, если смотреть в целом). К примеру: если на улице идёт дождь, то нужно взять с собой зонт, иначе брать его незачем. Другой пример из жизни, но уже не столько про решения, сколь описывающий определённые условия состояния обычной питьевой воды: если температура воды становится равной 100 градусам по Цельсию, то она закипает, иначе, если температура воды ниже 0 градусов по Цельсию, то она становится льдом, иначе при любых других условиях вода находится в жидком состоянии и вместе с тем не является закипевшей.

Так же как и людям, программам необходимо "уметь" принимать решения, то есть выполнять какие-то операции при заданных программистом условиях и не выполнять какие-то другие операции при иных условиях. На этом факте в большинстве случаев и строится логика программ: практически любой программе необходимо выполнять какие-то операции или действия, в зависимости от определённых условий.

Операторы if и switch, доступные в языке C++, как раз и служат этой цели - позволить программе "ветвиться" и исполнять те или иные операции, в зависимости от условий, расставленных в коде программы разработчиком.

Оператор if

Синтаксис оператора if в языке C++ выглядит следующим образом:

if ( /* основное_условие */ ) {
   // операторы, выполняемые при истинности основного условия
} else if ( /* дополнительное_условие_1 */ ) {
   // операторы, выполняемые при истинности дополнительного_условия_1
} else if ( /* дополнительное_условие_2 */ ) {
   // операторы, выполняемые при истинности дополнительного_условия_2
} else if ( /* ... дополнительное_условие_N */ ) {
   // операторы, выполняемые при истинности дополнительного_условия_N
} else {
   // операторы, выполняемые в случае, когда ни основное условие, ни все дополнительные условия не сработали
}

Сразу скажу, что блоки else if для оператора if являются опциональными, как и блок else. То есть если Вам не нужно накладывать каких-то дополнительных условий, Вы можете просто написать:

// какие-то операторы, идущие перед условием

if ( /* основное_условие */ ) {
   // операторы, выполняемые при истинности основного условия
}

// какие-то другие операторы, идущие после условия

Точно так же Вы можете задать только основное условие и блок else, который будет выполняться в случае, если основное условие в if не равно true и не равно 1:

// какие-то операторы, идущие перед условием

if ( /* основное_условие */ ) {
   // операторы, выполняемые при истинности основного условия
} else {
   // если основное условие не выполнилось (т.е. если оно не равно true и не равно 1), 
   // то мы попадём в блок else
}

// какие-то другие операторы, идущие после условия

Помимо вышеперечисленных особенностей оператора if расскажу ещё про одну - для оператора if и его блоков else if, else не обязательно указывать фигурные скобки { }, однако в этом случае вы ограничены ровно одним оператором для соответствующего блока if, else if или else. Т.е. первую форму из представленных выше можно написать так:

if ( /* основное_условие */ )
   // оператор, выполняемый при истинности основного условия
else if ( /* дополнительное_условие_1 */ )
   // оператор, выполняемый при истинности дополнительного_условия_1
else if ( /* дополнительное_условие_2 */ )
   // оператор, выполняемый при истинности дополнительного_условия_2
else if ( /* ... дополнительное_условие_N */ )
   // оператор, выполняемый при истинности дополнительного_условия_N
else
   // оператор, выполняемый в случае, когда ни основное условие, ни все дополнительные условия не сработали

Примечание: несмотря на то, что такая форма "без фигурных скобок" допустима синтаксисом языка C++, считается, что подобная форма оператора if и его веток else if и else не относится к лучшим практикам написания кода. Причина тому проста: разработчику крайне легко забыть о том, что при такой форме есть ограничение на использование ровно одного оператора, который должен идти после каждой развилки. Если же указать больше одного оператора, программа может повести себя непредсказуемо, и Вы будете потом долго искать ошибку в своём коде, пытаясь найти проблему. Поэтому старайтесь всегда использовать форму с фигурными скобками - даже тогда, когда у Вас в блоке только один оператор и "кажется, что скобки излишни". Скобки повышают читаемость кода и "прозрачность" всех развилок оператора if, а также предотвращают от возникновения неочевидных дефектов в Вашем коде.

Пример дефекта в программе, где разработчик забыл о том, что в форме "без фигурных скобок" для оператора if должен присутствовать строго один оператор:

    // В этом примере строка "THIS STRING WILL BE ALWAYS PRINTED!" будет выведена всегда!
    // Хотя "по отступам" разработчику может казаться, что она также относится к блоку else, 
    // и он ожидает, что она будет выведена только при входе программы в блок else
    if (input == 1)
        cout << "You entered one" << endl;
    else if (input == 2)
        cout << "You entered two" << endl;
    else if (input == 3)
        cout << "You entered three" << endl;
    else        
        cout << "You entered something else..." << endl;
        cout << "THIS STRING WILL BE ALWAYS PRINTED!";

Теперь давайте перейдем к небольшому примеру программы, который показывает все вышеперечисленные формы оператора if:

#include <iostream>

using namespace std;

int main() {
    int x = 0;

    cout << "Enter value for 'x': ";
    cin >> x;

    // Пример оператора if с блоком else и без блоков else if
    if (x > 0) {
        cout << "x is greater than 0" << endl;
    } else {
        cout << "x is less than or equal to 0" << endl;
    }

    int y = 0;
    cout << "Enter value for 'y': ";
    cin >> y;

    // Пример простого оператора if без блоков else if и else
    if (y == 0) {
        cout << "y is equal to zero!" << endl;
    }

    int z = 0;
    cout << "Enter value for 'z': ";
    cin >> z;

    // Пример оператора if с одним блоком else if и блоком else
    if (z < 0) {
        cout << "You are in the main if block" << endl;
        cout << "z is less than 0" << endl;
    } else if (z == 0) {
        cout << "You are in the else if block" << endl;
        cout << "z is equal to zero!" << endl;
    } else {
        cout << "You are in the else block" << endl;
        cout << "z is greater than 0" << endl;
    }

    int input;
    cout << "Enter the number: ";
    cin >> input;

    // Пример оператора if с несколькими блоками else if и блоком else, где не используются фигурные скобки
    // В этом случае можно использовать строго по одному оператору на каждую развилку, и в нашем случае это cout << "..."
    if (input == 1)
        cout << "You entered one" << endl;
    else if (input == 2)
        cout << "You entered two" << endl;
    else if (input == 3)
        cout << "You entered three" << endl;
    else
        cout << "You entered something else..." << endl;
}

Попробуйте скомпилировать и запустить эту программу в среде Microsoft Visual Studio и понаблюдать за тем, как ведёт себя программа в зависимости от того, что Вы вводите с клавиатуры.

Оператор switch

Оператор switch позволяет проверить значение переменной на предмет соответствия заданному перечню значений. Каждое проверяемое значение называется случай (англ. case). Синтаксис оператора switch выглядит следующим образом:

switch( /* <основное_выражение> */) {
   case /* <константное_выражение_1> */ :
      // операторы, которые должны быть выполнены, если значение <основного_выражение> 
      // равно <константное_выражение_1>
      break; // опциональный оператор выхода из case
   case /* <константное_выражение_2> */ :
      // операторы, которые должны быть выполнены, если значение <основного_выражение> 
      // равно <константное_выражение_2>
      break; // опциональный оператор выхода из case
   // количество развилок case ничем не ограничено, можно задать их столько, сколько требуется
   default: // опиональная ветка "по умолчанию", в которую попадаем если ни один из case выше не сработал
      // операторы, выполняющиеся при попадании в ветку "по умолчанию"
}

Ниже показан пример использования оператора switch в программе на C++:

#include <iostream>

using namespace std;

int main() {
    int x = 0;

    cout << "Enter value for 'x': ";
    cin >> x;

    switch (x) {
    case 1:
        cout << "You entered 'one'" << endl;
        break;
    case 2:
        cout << "You entered 'two'" << endl;
        break;
    case 3:
        cout << "You entered 'three'" << endl;
        break;
    default:
        cout << "You entered something else" << endl;
    }
}

Оператор switch можно использовать только с целочисленными типами данных или с перечислениями. То есть, например, нельзя в нём указать переменную типа double, т.к. Вы получите в этом случае ошибку компиляции - "выражение должно иметь целочисленный или перечисляемый тип":

    double y = 0;

    switch (y) { // так написать нельзя, будет ошибка компиляции
    case 2.5:
        cout << "You entered 2.5" << endl;
    }

Вы можете использовать переменную перечисляемого типа в операторе switch. В примере кода ниже мы определили перечисляемый тип days и объявили переменную my_day со значением sunday. После чего эту переменную можно проверить с помощью оператора switch на одно из допустимых значений этого перечисляемого типа:

    enum days { sunday, monday, tuesday, wednesday, thursday, friday, saturday };

    days my_day = sunday;

    switch (my_day) {
    case sunday:
        cout << "My day is Sunday!" << endl;
        break;
    case monday:
        cout << "My day is Monday!" << endl;
        break;
    case tuesday:
        cout << "My day is Tuesday!" << endl;
        break;
    default:
        cout << "My day is some other that is not 'Sunday', 'Monday' or 'Tuesday'!" << endl;
    }

Напоследок ещё несколько моментов, которые нужно запомнить про оператор switch: 

  • количество веток case никак не ограничено, можете указать столько, сколько требуется
  • ветка по умолчанию default может как присутствовать, так и отсутствовать - аналогично тому как для оператора if блок else является опциональным. Если она присутствует, она должна быть последней, после всех других веток case.
  • когда найдена нужная ветка case, которая соответствует значению выражения, заданного в switch, то операторы, которые в ней присутствуют, исполняются до тех пор, пока не будет найден оператор break, который приводит к передаче управления оператору, следующему за оператором switch.
  • Оператор break является опциональным, Вы можете объединить несколько веток case, если требуется выполнять какие-то операторы для набора допустимых значений.

Последнее утверждение из списка выше (о том, что оператор break является опциональным) продемонстрируем на примере:

    enum days { sunday, monday, tuesday, wednesday, thursday, friday, saturday };

    days my_day = sunday;

    switch (my_day) {
    case monday:
    case tuesday:
    case wednesday:
    case thursday:
    case friday:        
        cout << "My day is a working day!" << endl;
        break;
    case sunday:
    case saturday:
        cout << "My day is a day off!" << endl;
        break;    
    default:
        cout << "You specified some strange unknown day!" << endl;
    }

Как видим, мы можем объединить сразу несколько веток case, указав их друг за другом и задав для них общее действие в виде одного или нескольких операторов. В этом примере мы выведем одно  и то же сообщение для всех рабочих дней с понедельника по пятницу и другое сообщение для случая, когда это суббота или воскресенье. В случае, если мы нашли какое-то непредвиденное значение, то в ветке default мы отобразим сообщение о том, что был задан какой-то неизвестный странный день.

На этом обзор операторов if и switch завершён, обязательно попробуйте их в действии, т.к. они являются фундаментальными в языке C++, как и циклы. Напишите о своём опыте с этими операторами в комментариях к этой статье.

Яндекс.Метрика