View Categories

Оператор выбора

Для создания ветвления в программе также существует оператор выбора switch, в общем виде он выглядит так:

switch (значение) {
    case вариант1:
        // код
        break;

    case вариант2:
        // код
        break;

    case вариант3:
        // код
        break;

    default:
        // код
        break;
}

Оператор перейдёт к коду под меткой с вариантом, который совпадает со значением. Если такого варианта нет - выполнится код под меткой default.

Конструкция switch-case по сути является надстройкой над оператором goto, где кейсы - это метки

  • switch принимает только целочисленные значения
  • case может быть только целочисленной константой
  • case не должны повторяться
  • default будет выполнен, если не найдётся нужный вариант. Необязательная метка

break #

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

switch (var) {
    case 0:
        if (условие) break;
        // ...
        break;
}

Fallthrough #

Если не вызвать break в конце кода метки - программа перейдёт к выполнению кода следующей по порядку метки, этот переход называется fallthrough (провал) - из одной метки в другую. Провал можно использовать для создания сложных конструкций:

switch (var) {
    case 0:
        // выполнить, если var == 0
        break;

    case 1:
        // выполнить, если var == 1
        break;

    case 2:
        // выполнить, если var == 2

    case 3:
        // выполнить, если var == 2 или 3

    case 4:
        // выполнить, если var == 2, 3 или 4
        break;
}

Область видимости #

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

switch (var) {
    case 0:
        int a;
        break;

    case 1:
        int a;  // ошибка компиляции, такая переменная уже есть выше
        break;
}

Для решения этой проблемы достаточно обернуть код под меткой в блок:

switch (var) {
    case 0: {
        int a;
        } break;

    case 1: {
        int a;
        } break;
}

Скорость работы #

Логика switch-case может показаться похожей на if-else, но работают они абсолютно по разному: если if-else проверяет каждое условие по порядку, пока не дойдёт до нужного, то switch сразу выбирает нужный вариант. Switch работает значительно быстрее if-else, причём его скорость не зависит от количества вариантов, в отличие от if-else.

Диапазон значений в case #

Варианты для case можно задавать диапазоном значений:

switch (a) {
    case   0 ... 100: b = 1; break;
    case 101 ... 200: b = 2; break;
    case 201 ... 300: b = 3; break;
    case 301 ... 400: b = 4; break;
    case 401 ... 500: b = 5; break;
    case 501 ... 600: b = 6; break;
}

Этот пример равносилен конструкции на if-else, за исключением скорости работы:

if (a > 0 && a < 100) b = 1;
else if (a < 200) b = 2;
else if (a < 300) b = 3;
else if (a < 400) b = 4;
else if (a < 500) b = 5;
else if (a < 600) b = 6;

Switch + enum #

Довольно частый сценарий использования switch - разбор и реакция на значение переменной, которая получила своё значение где-то в другом месте программы. Например - обработка текущего режима, который выбран кнопкой:

enum Modes {
    Mode1,
    Mode2,
    Mode3,
};

Modes mode;

// ...

switch (mode) {
    case Modes::Mode1:
        break;

    case Modes::Mode2:
        break;

    case Modes::Mode3:
        break;
}

Здесь есть особенность: если в "кейсах" перечислены не все константы из enum, то компилятор выдаст предупреждение, что не все варианты обработаны. Если указать default - предупреждения не будет:

switch (mode) {
    case Modes::Mode1:
        break;

    default:
        break;
}
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Прокрутить вверх