Урок 3. Условия: if, else и switch
До сих пор программы выполняли все команды подряд. Но часто нужно поступить по-разному: если число чётное — одно, если нечётное — другое. Для этого есть условия.
if и else
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if (n % 2 == 0) {
cout << "even\n";
} else {
cout << "odd\n";
}
return 0;
}7oddВ круглых скобках после if — условие. Если оно истинно, выполняется блок в фигурных скобках сразу за ним, иначе — блок после else. Часть с else можно не писать: тогда при ложном условии программа просто идёт дальше.
Сравнения
| Запись | Значение |
|---|---|
a == b | равно |
a != b | не равно |
a < b, a > b | меньше, больше |
a <= b, a >= b | меньше или равно, больше или равно |
Результат сравнения — true или false (тип bool).
Равенство проверяется двумя знаками: ==. Один знак = — это присваивание. Запись if (x = 5) не сравнивает, а кладёт в x пятёрку, и условие всегда истинно. С ключом -Wall компилятор предупреждает об этом: suggest parentheses around assignment used as truth value.
Несколько вариантов: else if
Когда вариантов больше двух, условия ставят цепочкой. Они проверяются сверху вниз, и выполняется только первый подошедший блок:
#include <iostream>
using namespace std;
int main() {
int score;
cin >> score;
if (score >= 90) {
cout << "excellent\n";
} else if (score >= 70) {
cout << "good\n";
} else if (score >= 50) {
cout << "pass\n";
} else {
cout << "fail\n";
}
return 0;
}75goodДля 75 первое условие ложно, второе истинно — выводится good, а остальные условия уже не проверяются. Порядок важен: если поставить score >= 50 первым, все от 50 до 100 получат pass.
Логические операторы
Условия соединяются:
&&— «и»: истинно, когда истинны оба условия;||— «или»: истинно, когда истинно хотя бы одно;!— «не»: меняет истину на ложь и наоборот.
Классический пример — високосный год. Год високосный, если делится на 4, но не на 100, или если делится на 400:
#include <iostream>
using namespace std;
int main() {
int year;
cin >> year;
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
cout << "leap\n";
} else {
cout << "not leap\n";
}
return 0;
}1900not leap1900 делится на 4 и на 100, но не на 400, поэтому он не високосный, а 2000 — високосный.
&& и || вычисляются сокращённо: если по левой части ответ уже ясен, правая не проверяется. Это удобно: if (b != 0 && a % b == 0) не поделит на ноль, потому что при b == 0 вторая часть не выполнится.
Запись 1 < x < 10 в C++ не значит «x между 1 и 10». Сначала считается 1 < x (это 0 или 1), и результат сравнивается с 10 — условие истинно при любом x. Пишите 1 < x && x < 10.
Фигурные скобки
Если в блоке одна команда, скобки можно не ставить: if (x < 0) x = -x;. Но лучше ставить всегда. Без них легко ошибиться, когда в блок потом добавляют вторую строку: под условием окажется только первая, хотя отступы будут говорить другое. Отступы для компилятора ничего не значат — важны только скобки.
switch
Когда одну переменную сравнивают с несколькими точными значениями, удобен switch:
#include <iostream>
using namespace std;
int main() {
int day;
cin >> day;
switch (day) {
case 6:
case 7:
cout << "weekend\n";
break;
case 1:
cout << "Monday\n";
break;
default:
cout << "workday\n";
break;
}
return 0;
}6weekendcase — вариант значения, default — все остальные. break выходит из switch. Если break забыть, выполнение «проваливается» в следующий case — так здесь нарочно сделано для 6 и 7, но чаще это ошибка.
switch работает с целыми числами и символами (char); строки и дробные числа в нём сравнивать нельзя.
Тернарный оператор
Короткая запись «если — то — иначе», которая сама является значением: условие ? если_да : если_нет. «Тернарный» значит «из трёх частей»: условие и два варианта.
#include <iostream>
using namespace std;
int main() {
int a = 4, b = 9;
int biggest = (a > b) ? a : b;
cout << biggest << "\n";
cout << (a % 2 == 0 ? "a is even" : "a is odd") << "\n";
return 0;
}9
a is evenДля простых случаев это удобно, но вложенные тернарные операторы читаются плохо — тогда лучше if.
Дробные числа сравнивают осторожно
Дробные числа хранятся приблизительно, поэтому 0.1 + 0.2 == 0.3 — ложь:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double x = 0.1 + 0.2;
cout << (x == 0.3) << "\n";
cout << (fabs(x - 0.3) < 1e-9) << "\n";
return 0;
}0
1Дробные числа сравнивают с допуском: разница меньше маленького числа (здесь 1e-9, то есть 10⁻⁹) считается равенством. fabs — модуль дробного числа, он из <cmath>.
Коротко
if (условие) { ... } else { ... }; цепочка вариантов —else if.- Сравнение —
==, а=— присваивание. &&— «и»,||— «или»,!— «не»; вычисляются сокращённо.switchсравнивает одно целое значение с вариантамиcase; не забывайтеbreak.условие ? a : b— короткий выбор из двух значений.- Дробные числа сравнивайте с допуском, а не через
==.