В языке 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++, как и циклы. Напишите о своём опыте с этими операторами в комментариях к этой статье.