1.4.5. Оператор switch | Электроника для всех

Содержание
Возврат к предыдущей части 1.4.1..1.4.4 Операторы If, Then, Else

Оператор switch предназначен для организации выбора из множества различных вариантов. Формат оператора следующий:

1
2
3
4
5
6
7
8
9
     switch ( выражение )
     {   [объявление]
              :
           [ case  константное-выражение1]: [ список-операторов1]
           [ case  константное-выражение2]: [ список-операторов2]
              :
              :
           [ default: [ список операторов ]]
     }

Выражение, следующее за ключевым словом switch в круглых скобках, может быть любым выражением, допустимыми в языке СИ, значение которого должно быть целым. Отметим, что можно использовать явное приведение к целому типу, однако необходимо помнить о тех ограничениях и рекомендациях, о которых говорилось выше.

Значение этого выражения является ключевым для выбора из нескольких вариантов.

Тело оператора smitch состоит из нескольких операторов, помеченных ключевым словом case с последующим константным-выражением. Следует отметить, что использование целого константного выражения является существенным недостатком, присущим рассмотренному оператору.

Так как константное выражение вычисляется во время трансляции, оно не может содержать переменные или вызовы функций. Обычно в качестве константного выражения используются целые или символьные константы.

Все константные выражения в операторе switch должны быть уникальны. Кроме операторов, помеченных ключевым словом case, может быть, но обязательно один, фрагмент помеченный ключевым словом default.

Список операторов может быть пустым, либо содержать один или более операторов. Причем в операторе

switch не требуется заключать последовательность операторов в фигурные скобки.

Отметим также, что в операторе switch можно использовать свои локальные переменные, объявления которых находятся перед первым ключевым словом case, однако в объявлениях не должна использоваться инициализация.

Схема выполнения оператора switch следующая:

  • вычисляется выражение в круглых скобках;
  • вычисленные значения последовательно сравниваются с константными выражениями, следующими за ключевыми словами case;
  • если одно из константных выражений совпадает со значением выражения, то управление передается на оператор, помеченный соответствующим ключевым словом case;

— если ни одно из константных выражений не равно выражению, то управление передается на оператор, помеченный ключевым словом default, а в случае его отсутствия управление передается на следующий после switch оператор.

Отметим интересную особенность использования оператора switch: конструкция со словом default может быть не последней в теле оператора switch. Ключевые слова case и default в теле оператора switch существенны только при начальной проверке, когда определяется начальная точка выполнения тела оператора

switch. Все операторы, между начальным оператором и концом тела, выполняются вне зависимости от ключевых слов, если только какой-то из операторов не передаст управления из тела оператора switch. Таким образом, программист должен сам позаботится о выходе из case, если это необходимо. Чаще всего для этого используется оператор break.

Для того, чтобы выполнить одни и те же действия для различных значений выражения, можно пометить один и тот же оператор несколькими ключевыми словами case.

Пример:

1
2
3
4
5
6
7
8
9
     int i=2;
      switch (i)
        {
         case 1: i += 2;
         case 2: i *= 3;
         case 0: i /= 2;
         case 4: i -= 5;
         default:      ;
     }

Выполнение оператора switch начинается с оператора, помеченного case 2. Таким образом, переменная i получает значение, равное 6, далее выполняется оператор, помеченный ключевым словом case 0, а затем case 4, переменная i примет значение 3, а затем значение -2. Оператор, помеченный ключевым словом default, не изменяет значения переменной.

Рассмотрим ранее приведенный пример, в котором иллюстрировалось использование вложенных операторов if, переписанной теперь с использованием оператора switch.

1
2
3
4
5
6
7
8
9
10
    char ZNAC;
     int x,y,z;
     switch (ZNAC)
     {
          case '+':  x = y + z;    break;
          case '-':  x = y - z;    break;
          case '*':  x = y * z;    break;
          case '/':  x = u / z;    break;
          default : ;
        }

Использование оператора break позволяет в необходимый момент прервать последовательность выполняемых операторов в теле оператора switch, путем передачи управления оператору, следующему за

switch.

Отметим, что в теле оператора switch можно использовать вложенные операторы switch, при этом в ключевых словах case можно использовать одинаковые константные выражения.

Пример:

1
2
3
4
5
6
7
8
9
10
11
12
13
       :
     switch (a)
      {
        case 1: b=c; break;
        case 2:
            switch (d)
            {   case 0:  f=s;  break;
                case 1:  f=9;  break;
                case 2:  f-=9; break;
            }
         case 3: b-=c; break;
         :
      }

1.

4.6. Оператор break
Оператор break обеспечивает прекращение выполнения самого внутреннего из объединяющих его операторов switch, do, for, while. После выполнения оператора break управление передается оператору, следующему за прерванным.

Читать далее. Раздел 1.4.7 Оператор for
Содержание

Есть ли в Python оператор switch case?

UPD (16.02.2022)

Обновление добавлено по причине появления конструкции match-case в python 3.10. Ответ, который дополняет в этой ветке и расширенный ответ в связи с изменениями.

Ответ ниже продолжает быть актуальным, как в версиях ниже 3.10, так и в версии 3.10

UPD END

Для начала, ничего особенно плохого в использовании конструкции if-elif-else нет.

При желании можно найти несколько альтернатив.


Использование словарей

Довольно распространённый способ организации конструкции switch-case в Python — это использование словаря. Проще показать на примере:

unit_to_multiplier = {
    'mm': 10**-3,
    'cm': 10**-2,
    'dm': 10**-1,
    'm': 1,
    'km': 10**3
}

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

try:
    mult = unit_to_multiplier['cm']
except KeyError as e:
    # можно также присвоить значение по умолчанию вместо бросания исключения
    raise ValueError('Undefined unit: {}'.format(e.args[0]))

Если вы твёрдо уверены, что значение всегда будет присутствовать в словаре, можете опустить блок try-except и быть готовым ловить исключение в другом месте.

Некоторой вариацией этого подходя будет предварительная проверка значения в условии:

if unit in unit_to_multiplier:
    mult = unit_to_multiplier[unit]
else:
    # обработка отсутствия значения в словаре

В Python принято использовать подход, звучащий примерно так: «лучше попробовать и получить ошибку, чем каждый раз спрашивать разрешение», поэтому более предпочтительный подход с использованием исключений.

Если хочется использовать значение по умолчанию в случае, если ключ отсутствует, удобно использовать метод get:

mult = unit_to_multiplier.get('ultra-meter', 0)

Если словарь вам требуется один раз, можно объединить эти выражения в одно:

unit_to_multiplier = {
    'mm': 10**-3,
    'cm': 10**-2,
    'dm': 10**-1,
    'm': 1,
    'km': 10**3
}.get('km', 0)

На этом возможности этого подхода не заканчиваются. Можно использовать условные выражения в качестве ключей словаря:

def get_temp_description(temp):
    return {
               temp < -20: 'Холодно',
        -20 <= temp < 0:   'Прохладно',
          0 <= temp < 15:  'Зябко',
         15 <= temp < 25:  'Тепло',
         25 <= temp:       'Жарко'
    }[True]

Этот словарь после вычисления будет иметь два ключа True и False. Нас интересует ключ True. Будьте внимательны, что условия не перекрываются!

Подобные словари могут проверять произвольное свойство, например, тип (источник примера):

selector = {
    type(x) == str  : "it's a str",
    type(x) == tuple: "it's a tuple",
    type(x) == dict : "it's a dict"
}[1]   # можно использовать число 1 как синоним True

При необходимости более сложных действий хранить функцию в качестве значения по каждому ключу:

import operator
operations = {
    '+': operator. add,
    '*': lambda x, y: x * y,
    # ...
}
def calc(operation, a, b): 
    return operations[operation](a, b)

Будьте внимательны при использовании словаря с функциями — убедитесь, что вы не вызываете эти функции внутри словаря, а передаёте по ключу; иначе все функции будут выполняться каждый раз при конструировании словаря.


Другие способы

Приведены скорее для ознакомления, чем для реального использования.

  1. Использование функций с шаблонными именами

    Создадим класс, в котором напишем несколько методов вида:

     def process_first(self):
         ...
     def process_second(self):
         ...
     ...
    

    И один метод-диспетчер:

     def dispatch(self, value):
         method_name = 'process_' + str(value)
         method = getattr(self, method_name)
         return method()
    

    После этого можно использовать метод dispatch для выполнения соответствующей функции, передавая её суффикс, например x.dispatch('first').

  2. Использование специальных классов

    Если есть желание использовать синтаксис switch-case в максимально похожем стиле, можно написать что-то вроде следующего кода:

     class switch(object):
         def __init__(self, value):
             self.value = value  # значение, которое будем искать
             self.fall = False   # для пустых case блоков
         def __iter__(self):     # для использования в цикле for
             """ Возвращает один раз метод match и завершается """
             yield self.match
             raise StopIteration
         def match(self, *args):
             """ Указывает, нужно ли заходить в тестовый вариант """
             if self.fall or not args:
                 # пустой список аргументов означает последний блок case
                 # fall означает, что ранее сработало условие и нужно заходить 
                 #   в каждый case до первого break
                 return True
             elif self.value in args:
                 self.fall = True
                 return True
             return False
    

    Используется следующим образом:

     x = int(input())
     for case in switch(x):
         if case(1): pass
         if case(2): pass
         if case(3): 
             print('Число от 1 до 3')
             break
         if case(4): 
             print('Число 4')
         if case(): # default
             print('Другое число')
    
  3. Использование операторов and и or.

    Довольно небезопасный способ, см. пример:

     # Условная конструкция
     Select Case x
        Case x<0    : y = -1 
        Case 0<=x<1 : y =  0
        Case 1<=x<2 : y =  1
        Case 2<=x<3 : y =  2
        Case Else   : y =  'n/a'
     End Select  
     # Эквивалентная реализация на Python
     y = ((     x < 0 and 'first segment') or 
          (0 <= x < 1 and 'second segment') or 
          (1 <= x < 2 and 'third segment') or 
          (2 <= x < 3 and 'fourth segment') or 'other segment')
    

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

    (t вычисляющееся как True, f вычисляется как False):

     f and x = f
     t and x = x
     f or  x = x
     t or  x = t
    

    Предложенный способ вычислений будет работать только в том случае, если второй аргумент оператора and всегда будет содержать True-выражение, иначе этот блок всегда будет пропускаться. Например:

     y = ((     x < 0 and -1) or 
          (0 <= x < 1 and 0) or 
          (1 <= x < 2 and 1) or 
          (2 <= x < 3 and 2) or 'n/a')
    

    Будет работать неправильно в случае 0 <= x < 1, т.к. выражение 0 <= x < 1 and 0 равно 0, и из-за этого управление перейдёт следующему аргументу or, вместо того, чтобы вернуть этот ноль в качестве результата выражения.

  4. Использование исключений

    Если объявить несколько функций:

     import sys
     class case_selector(Exception):
        def __init__(self, value):  # один обязательный аргумент
           Exception.__init__(self, value)
     def switch(variable):
        raise case_selector(variable)
     def case(value):
        exc_сlass, exс_obj, _ = sys.exc_info()
        if exc_сlass is case_selector and exс_obj.args[0] == value: 
            return exс_class
        return None
    

    Здесь используется функция sys.exc_info, которая возвращает набор из информации об обрабатываемом исключении: класса, экземпляра и стека.

    Код с использованием этих конструкций будет выглядеть следующим образом:

     n = int(input())
     try:
        switch(n)
     except ( case(1), case(2), case(3) ):
        print "Число от 1 до 3"
     except case(4):
        print "Число 4"
     except:
        print "Другое число"
    

Оператор Swift switch (с примерами)

В этой статье вы научитесь использовать операторы управления switch для управления потоком выполнения вашей программы.

Оператор switch позволяет нам выполнить блок кода среди многих альтернатив.

Синтаксис оператора switch в Swift:

 switch (выражение) {
  значение случая1:
    // заявления
  значение случая2:
    // заявления
  ...
  ...
        
  дефолт:
    // заявления
} 

Оператор switch вычисляет выражение в круглых скобках () .

  1. Если результат выражения равен значение1 , выполняются операторы случая значение1: .
  2. Если результат выражения равен значение2 , выполняются операторы вида case значение2: .
  3. Если совпадения нет, выполняются операторы варианта по умолчанию .

Примечание: Мы можем сделать то же самое с лестницей if…else…if. Однако синтаксис оператора switch чище и намного проще для чтения и записи.


Блок-схема оператора Switch

Блок-схема оператора Switch

Пример 1: Простая программа, использующая оператор Switch

 // программа для определения дня недели
пусть день недели = 4
переключить день недели {
  Случай 1:
    распечатать("воскресенье")

  случай 2:
    печатать("Понедельник")

  случай 3:
    печать("вторник")

  случай 4:
    печать("среда")

  случай 5:
    печать("Четверг")

  случай 6:
    распечатать("пятница")

  случай 7:
    печать("суббота")

  дефолт:
    print("Неверный день")
} 

Выход

  Среда  

В приведенном выше примере мы присвоили 4 переменной dayOfWeek . Теперь переменная сравнивается со значением каждого оператора case.

Поскольку значение соответствует case 4 , внутри case выполняется оператор print("Wednesday") и программа завершается.


Оператор Switch с отказом

Если мы используем fallthrough ключевое слово внутри оператора case, элемент управления переходит к следующему case, даже если значение case не совпадает с выражением switch. Например,

 // программа для определения дня недели
пусть день недели = 4
переключить день недели {
  Случай 1:
    распечатать("воскресенье")

  случай 2:
    печатать("Понедельник")

  случай 3:
    печать("вторник")

  случай 4:
    печать("среда")
    провалиться

  случай 5:
    печать("Четверг")

  случай 6:
    распечатать("пятница")

  случай 7:
    печать("суббота")

  дефолт:
    print("Неверный день")
} 

Выход

  Среда
Четверг  

В приведенном выше примере, поскольку значение совпадает с case 4 , оператор print("Среда") внутри case выполняется

Мы также использовали ключевое слово fallthrough . Таким образом, оператор print("Четверг") внутри case 5 выполняется, даже если case не совпадает с оператором case.


Пример 2. Оператор Switch с диапазоном

 пусть возрастная группа = 33
сменить возрастную группу {
  случай 0...16:
    печатать("Ребенок")
  случай 17...30:
    print("Молодые люди")
  случай 31...45:
    print("Взрослые среднего возраста")
  дефолт:
    print("Пожилые люди")
} 

Выход

  Взрослые среднего возраста  

В приведенном выше примере вместо одного значения мы использовали числовые диапазоны для каждого случая: случай 0...16 , случай 17...30 и случай 31 ...45 .

Здесь значение ageGroup — это 33 из диапазона 32...45 . Следовательно, выполняется оператор print("Взрослые среднего возраста") .


Кортеж в операторе Switch

В Swift мы также можем использовать кортежи в операторах switch. Например,

 let info = ("Дуайт", 38)
// соответствие полным значениям кортежа
переключать информацию {
  случай ("Дуайт", 38):
    print("Дуайту 38 лет")
  случай ("Майкл", 46):
    print("Майклу 46 лет")
  дефолт:
    печатать("Неизвестно")
} 

Выход

  Дуайту 38 лет 
   

В приведенном выше примере мы создали кортеж с именем info со значениями: "Дуайт" и 38 .

Здесь вместо одного значения каждый оператор case также включает кортежи: case("Dwight", 38) и case("Micheal", 46) .

Теперь значение info сравнивается с каждым оператором case. Поскольку значение соответствует case ("Дуайт", 38) , выполняется оператор print("Дуайту 38 лет") .

Чтобы узнать больше о кортежах, посетите Swift Tuple.

Переключить регистр в операторе и выражении C#

Автор Алекс

В этом посте мы рассмотрим относительно новую функцию — , когда ключевое слово в контексте оператора switch и выражения switch.

Ключевое слово когда используется для указания условия в case метке оператора switch или выражения. Это обеспечивает детальный контроль над тем, какой раздел переключателя будет выполняться на основе условия (выражение, которое оценивается как логическое).

Помимо теоретической части, я постарался включить много практических и простых для понимания примеров, когда этот функционал может быть полезен. Не стесняйтесь прыгать прямо туда, если вы просто хотите посмотреть на некоторые примеры.

Состав:

  • Обзор
  • Оператор Switch и ключевое слово «когда»
    • Терминология
    • Сопоставление с шаблоном: введите шаблон и ключевое слово «когда»
    • Fall Through и Variable Scope
  • Примеры C# Switch Case
    • Больше или
    • Диапазон
    • или между
    • Содержит
    • Нулевой или пустой
    • Сравнение без учета регистра
    • Начинается с
    • Регулярное выражение
    • Тип/тип
    • Общий тип
  • C# 8. 0 — Использование «когда» в выражении переключения
  • C# 9.0 — использование реляционного шаблона вместо «когда»
  • Полезные ссылки

Обзор

Введение ключевого слова when в оператор switch позволило обрабатывать более сложные сценарии, когда метки case не могут быть выражены только с помощью шаблонов констант или типов.

В частности, вот список тем, которые мы обсудим, а также версии C#, когда они были представлены:

  • Оператор Switch — хорошо знакомая опция, пожалуй, любому программисту, она присутствует во всех версиях C#
  • Когда ключевое слово — начиная с C# 7.0 когда ключевое слово можно использовать в операторе switch, в этом посте много говорится об этой функции
  • Выражение
  • Switch — введено в C# 8.0 и обеспечивает switch -подобную семантику в контексте выражения
  • Реляционный шаблон — функция C# 9.0, которая позволяет указывать условия даже без , когда ключевое слово

Все темы, упомянутые выше, дополнены набором примеров и распространенных вариантов использования, перечисленных в разделе «Примеры C# Switch Case». Это должно дать хорошее представление о том, как использовать switch-case-когда на практике.

Давайте посмотрим на оператор switch и на то, как в него вписывается ключевое слово when .

ПРИМЕЧАНИЕ.0280 важен порядок этикеток .

Терминология

В приведенном ниже фрагменте кода используется очень простой оператор switch, чтобы ввести некоторую терминологию, которую мы будем использовать в этом посте. Это довольно интуитивно понятно, но стоит упомянуть, чтобы привести всех на одну страницу:

  • Соответствие выражению
  • Этикетка для корпуса
  • Метка по умолчанию
  • Секция переключателя
 switch (caseSwitch) // Выражение совпадения — может быть любым ненулевым выражением
{
    случай 1: // Метка случая 1 Раздел переключения START
    случай 2: // Метка случая 2
        // ...
        ломать; // Раздел переключения END
    случай 3: // Метка случая 3 Раздел переключения START
        // . ..
        ломать; // Раздел переключения END
    default: // Секция переключения меток по умолчанию START
        // ...
        ломать; // Раздел переключения END
}
 

Сопоставление с шаблоном: шаблон типа и ключевое слово «когда»

Шаблон типа — интересная функция, поскольку она расширяет диапазон возможных вариантов использования, в которых может применяться регистр переключения.

Type Pattern — это новое дополнение к возможностям сопоставления шаблонов операторов switch в C# 7, которое дополняет уже существующий и хорошо известный постоянный шаблон.

В большинстве случаев имеет смысл использовать , когда ключевое слово в сочетании с шаблоном типа. Тем не менее, его можно использовать и с постоянным шаблоном, но я изо всех сил пытаюсь придумать значимые примеры.

Ниже приведен синтаксис, иллюстрированный псевдоподобным кодом:

 переключатель (caseSwitch)
{
    ...
    case TypeA myVar, когда myVar.Size > 0:
        ... 
        ломать;
    case   when :
        ...
        ломать;
    ...
}
 

Fall Through и Variable Scope

Стоит отметить, что, как и в случае с обычными метками case, метки с ключевым словом и также следуют поведению провала.

Провал означает, что несколько меток case приводят к выполнению одного блока кода. Или, другими словами, раздел дела может иметь несколько меток дела.

ПРИМЕЧАНИЕ. Переменная, определенная в метке дела, имеет область действия в соответствующем разделе дела . Пожалуйста, обратитесь к терминологии, касающейся этикетки корпуса и значения раздела корпуса.

Итак, единственная небольшая оговорка здесь заключается в том, что переменные, определенные в нескольких метках одного и того же раздела case, должны иметь разные имена. К счастью, это совсем не проблема, так как компилятор помогает нам, подсвечивая такие ошибки.

 переключатель (caseSwitch)
{
    ...
    case TypeA myVarA, когда myVarA.Size > 0:
    case TypeB myVarB, когда myVarB.Color == "red":
        ...
        ломать;
    ...
}
 

Примеры C# Switch Case

Теперь, учитывая, что мы рассмотрели формальную часть функциональности «переключатель case when», давайте посмотрим на некоторые распространенные варианты использования и на то, как ключевое слово when здесь пригодится.

Примеры ниже организованы в виде шпаргалки, основная идея во всех этих примерах одна и та же, просто найдите совпадение и получите решение!

Больше, Или

Давайте начнем с чрезвычайно простого случая, просто имея условие, состоящее из нескольких условий. В приведенном ниже примере мы используем операции GreaterThan или LessThan.

 переключатель (caseSwitch)
{
    case int x когда x > 5 || x < 0: // Больше или меньше
        // ...
        ломать;
    case int x когда x > 5 или < 0: // Более новый синтаксис
        // . ..
        ломать;
    // ...
}
 

Диапазон или между

Это достигается простым объединением нескольких ограничений в условной части, что довольно просто. В следующем примере мы проверяем, что целое число находится в диапазоне [0, 100].

 переключатель (caseSwitch)
{
    case int x when x >= 0 && x <= 100: // Стандартный подход
        // ...
        ломать;
    case int x когда x >= 0 и <= 100: // Более новый синтаксис
        // ...
        ломать;
    // ...
}
 

Содержит

Проверка наличия в строке подстроки. Тот же подход можно применить к коллекциям/массивам.

 переключатель (caseSwitch)
{
    case string s когда s.Contains("someValue"):
        // ...
        ломать;
    // ...
}
 

Null or Empty

Проверка того, является ли строка IsNullOrEmpty аналогично IsNullOrWhiteSpace .

 переключатель (caseSwitch)
{
    case string s когда string.IsNullOrEmpty(s):
        // ...
        ломать;
}
 

Сравнение без учета регистра

Сравнение строк без учета регистра.

 переключатель (caseSwitch)
{
    case string s когда s.Equals("someValue", StringComparison.InvariantCultureIgnoreCase):
        // ...
        ломать;
}
 9[0-9a-zA-Z]+$"):
        // ...
        ломать;
    // ...
}
 

Type/typeof

Мы использовали эту функцию много раз в этом посте, просто нужно объединить Type Pattern с , когда ключевое слово .

 переключатель (caseSwitch)
{
    case Rectangle x когда x.Area == 0:
        // ...
        ломать;
    // ...
}
 

Generic Type

Например, если предоставленное значение имеет тип List и этот список небольшой (менее 10 элементов), то мы хотим применить некоторую специальную обработку (например, использовать алгоритм грубой силы ).

 переключатель (caseSwitch)
{
    case List список, когда list.Count < 10:
        // ...
        ломать;
    // ...
}
 

C# 8.0 — Использование «когда» в выражении Switch

Выражение Switch — это новая конструкция, обеспечивающая семантику, подобную переключателю, в контексте выражения. Другими словами, он позволяет иметь функциональность, аналогичную оператору switch, но его можно использовать как выражение.

Мы не будем вдаваться в детали выражения switch, а посмотрим, как его использовать. Чтобы узнать больше о самом выражении switch, обратитесь к документации.

Использование очень похоже на обычный случай переключения, только несколько комментариев:

  • может быть Type Pattern или Constant Pattern
  • — это выражение, результатом которого является логическое значение
  • <выражение> возвращает значение
 var result = переключатель caseSwitch
{
     when  => , // Рука выражения
    int x когда x > 0 => 1, // Простой пример
    _ **=>** 0 // Постановка на охрану по умолчанию
};
 

C# 9.0 — использование реляционного шаблона вместо «когда»

Более того, в некоторых случаях нам даже не нужно ключевое слово when для указания некоторых ограничений — в C# 9 есть новая функция, называемая реляционным шаблоном.