Урок 3. Условия: if, else и switch
Программа редко выполняет все команды подряд: чаще она выбирает, что делать, — в зависимости от введённых данных. Для этого есть условный оператор if.
#include <stdio.h>
int main(void) {
int t;
scanf("%d", &t);
if (t < 0) {
printf("Мороз\n");
} else {
printf("Выше нуля\n");
}
return 0;
}-5МорозУсловие пишется в круглых скобках. Если оно верно, выполняется блок в фигурных скобках после if, иначе — блок после else. Часть else можно не писать: тогда при неверном условии ничего не произойдёт.
Если в блоке одна команда, фигурные скобки можно опустить: if (t < 0) printf("Мороз\n");. Но со скобками надёжнее: при добавлении второй команды без скобок она окажется вне условия и будет выполняться всегда.
Сравнения
| Запись | Значение |
|---|---|
a == b | равно |
a != b | не равно |
a < b, a > b | меньше, больше |
a <= b, a >= b | меньше или равно, больше или равно |
Сравнение на равенство — два знака ==. Запись if (x = 5) не сравнивает, а присваивает x значение 5, и условие всегда оказывается верным. Программа собирается, но работает неправильно. Ключ -Wall ловит эту ошибку: suggest parentheses around assignment used as truth value.
В C нет отдельного «истинно» и «ложно» в привычном виде: условие — это число. 0 — ложь, любое другое число — истина. Сравнение 5 > 3 даёт 1, 5 < 3 даёт 0. С C99 есть тип bool со значениями true и false; в C17 для него нужен #include <stdbool.h>.
Несколько вариантов: else if
#include <stdio.h>
int main(void) {
int score;
scanf("%d", &score);
if (score >= 90) {
printf("Отлично\n");
} else if (score >= 70) {
printf("Хорошо\n");
} else if (score >= 50) {
printf("Удовлетворительно\n");
} else {
printf("Неудовлетворительно\n");
}
return 0;
}75ХорошоУсловия проверяются сверху вниз, выполняется первая подходящая ветка — остальные пропускаются. Поэтому при 75 сработала ветка score >= 70, хотя 75 больше и 50. Порядок условий важен: если поставить score >= 50 первым, «Хорошо» и «Отлично» не выведутся никогда.
Логические операции
| Запись | Значение | Верно, когда |
|---|---|---|
a && b | и | верны оба условия |
a || b | или | верно хотя бы одно |
!a | не | условие неверно |
Классический пример — високосный год: он делится на 4, но не на 100, либо делится на 400.
#include <stdio.h>
int main(void) {
int y;
scanf("%d", &y);
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) {
printf("%d — високосный\n", y);
} else {
printf("%d — не високосный\n", y);
}
return 0;
}19001900 — не високосный&& выполняется раньше ||, но скобки делают условие понятнее — ставьте их. Проверка идёт слева направо и останавливается, как только ответ ясен: в b != 0 && a / b > 2 деления на ноль не будет, потому что при b == 0 вторая часть не вычисляется.
Двойное неравенство в C так не пишется: if (1 <= x <= 10) собирается, но значит не то, что кажется (сначала считается 1 <= x, получается 0 или 1, и это сравнивается с 10 — условие верно всегда). С -Wall gcc предупреждает: comparisons like 'X<=Y<=Z' do not have their mathematical meaning. Правильно: if (x >= 1 && x <= 10).
Дробные числа не сравнивайте через ==: из-за округления 0.1 + 0.2 == 0.3 неверно. Сравнивайте разницу с маленьким числом: fabs(a - b) < 1e-9 (функция fabs — из math.h).
Выбор по значению: switch
Когда нужно сравнить одну переменную с несколькими значениями, удобнее switch:
#include <stdio.h>
int main(void) {
int day;
scanf("%d", &day);
switch (day) {
case 1:
printf("Понедельник\n");
break;
case 2:
printf("Вторник\n");
break;
case 6:
case 7:
printf("Выходной\n");
break;
default:
printf("Другой день\n");
}
return 0;
}7Выходнойcase— значение, с которым сравнивается переменная.default— «все остальные значения».breakвыходит изswitch. Без него выполнение «проваливается» в следующийcase. Иногда это нужно (как у 6 и 7 выше), но чаще забытыйbreak— ошибка: выведутся сразу несколько вариантов.switchработает только с целыми числами и символами (case 'y':). Строки и дробные числа вcaseнельзя.
Тернарный оператор
Короткая форма «если — то — иначе», которая возвращает значение («тернарный» — из трёх частей: условие и два варианта):
#include <stdio.h>
int main(void) {
int a = 8, b = 3;
int max = (a > b) ? a : b;
printf("Наибольшее: %d\n", max);
printf("%d — %s\n", a, (a % 2 == 0) ? "чётное" : "нечётное");
return 0;
}Наибольшее: 8
8 — чётноеЗапись условие ? x : y даёт x, если условие верно, и y — если нет. Удобно для коротких выборов; для длинной логики понятнее обычный if. Формат %s выводит строку — о строках подробно в отдельном уроке.
Коротко
if (условие) { … } else { … }; цепочка —else if, выполняется первая подходящая ветка.- Сравнение —
==, а=— присваивание.-Wallпредупреждает оif (x = 5). - 0 — ложь, любое другое число — истина.
&&— и,||— или,!— не. - Двойное неравенство — через
&&:x >= 1 && x <= 10. Дробные числа не сравнивают через==. switch— для целых и символов; в конце каждогоcase—break.