Глиф Учебники

Урок 3. Условия: if, else и switch

Курс «C» · урок 3 из 10 · 4 минуты чтения

Программа редко выполняет все команды подряд: чаще она выбирает, что делать, — в зависимости от введённых данных. Для этого есть условный оператор if.

C
#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

C
#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 первым, «Хорошо» и «Отлично» не выведутся никогда.

score = 75 score >= 90 Отлично нет score >= 70 да Хорошо score >= 50 Удовлетворительно else Неудовлетворительно эти ветки не проверяются
При score = 75 условие score >= 90 ложно, и проверка переходит к score >= 70; оно верно — выполняется ветка «Хорошо», а следующие условия и else уже не проверяются.

Логические операции

ЗаписьЗначениеВерно, когда
a && bиверны оба условия
a || bиливерно хотя бы одно
!aнеусловие неверно

Классический пример — високосный год: он делится на 4, но не на 100, либо делится на 400.

C
#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;
}
Ввод
1900
Вывод
1900 — не високосный

&& выполняется раньше ||, но скобки делают условие понятнее — ставьте их. Проверка идёт слева направо и останавливается, как только ответ ясен: в 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).

неверно при x = 20 (1 <= x) <= 10 1 <= 20 даёт 1 1 <= 10 1 — истина, блок if выполнится при любом x: 0 или 1 всегда <= 10 верно при x = 20 x >= 1 && x <= 10 20 >= 1 даёт 1 20 <= 10 даёт 0 1 && 0 0 — ложь, блок if пропущен верно, только если верны оба
При x = 20 запись 1 <= x <= 10 считается как (1 <= x) <= 10: сначала получается 1, а 1 <= 10 верно, поэтому условие истинно; в записи x >= 1 && x <= 10 вторая часть даёт 0, и условие ложно.

Дробные числа не сравнивайте через ==: из-за округления 0.1 + 0.2 == 0.3 неверно. Сравнивайте разницу с маленьким числом: fabs(a - b) < 1e-9 (функция fabs — из math.h).

Выбор по значению: switch

Когда нужно сравнить одну переменную с несколькими значениями, удобнее switch:

C
#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
Вывод
Выходной
switch (day) day = 7 case 1:Понедельник case 2:Вторник case 6:как case 7 default:Другой день break break case 7: Выходной break код после switch switch (n) n = 2 case 1: один case 2: два case 3: три нет break вывод: два три без break выполнение идёт дальше
switch переходит сразу к подходящему case: при day = 7 выполняется «Выходной», и break выводит из switch; при n = 2 без break после case 2 выполняется и case 3 — выводится «два три».

Тернарный оператор

Короткая форма «если — то — иначе», которая возвращает значение («тернарный» — из трёх частей: условие и два варианта):

C
#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 выводит строку — о строках подробно в отдельном уроке.

Коротко

Проверьте себя

1. Что выведет программа при x = 0: if (x = 1) printf("A"); else printf("B");?
2. Как правильно проверить, что x от 1 до 10 включительно?
3. Что выведет программа при n = 2?
C
#include <stdio.h>

int main(void) {
    int n = 2;
    switch (n) {
        case 1: printf("один ");
        case 2: printf("два ");
        case 3: printf("три ");
    }
    printf("\n");
    return 0;
}
4. Какое значение условия C считает ложью?