Jump to content

Оператор переключения

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

Операторы переключения функционируют несколько аналогично if Заявление, используемое на языках программирования, таких как C / C ++ , C# , Visual Basic .net , Java и существует на самых высокоуровневых императивных языках программирования, таких как Pascal , ADA , C / C ++ , C# , [ 1 ] : 374–375  Visual Basic .net , Java , [ 2 ] : 157–167  и во многих других типах языка, используя такие ключевые слова , как switch, case, select или inspect.

Операторы коммутатора бывают двух основных вариантов: структурированный переключатель, как в Pascal, который занимает ровно одну ветвь, и неструктурированный коммутатор, как в C, который функционирует как тип Goto . Основные причины использования переключателя включают улучшение ясности, путем снижения повторяющегося кодирования и (если разрешение на эвристику ) также предлагает потенциал для более быстрого выполнения посредством более легкой оптимизации компилятора во многих случаях.

Пример оператора переключения в C
switch (age) {
  case 1:  printf("You're one.");            break;
  case 2:  printf("You're two.");            break;
  case 3:  printf("You're three.");
  case 4:  printf("You're three or four.");  break;
  default: printf("You're not 1, 2, 3 or 4!");
}

В своем тексту 1952 года введение в метаматематику Стивен Клейн формально доказал, что функция случая (функция if-then-else является ее простейшей формой) является примитивной рекурсивной функцией , где он определяет определение понятия «случаями» в следующем виде: следующим образом:

"#F. Функция φ определена таким образом

φ (x 1 , ..., x n ) =
  • φ 1 (x 1 , ..., x n ), если q 1 (x 1 , ..., x n ),
  • . . . . . . . . . . . .
  • φ m (x 1 , ..., x n ), если q m (x 1 , ..., x n ),
  • φ m+1 (x 1 , ..., x n ) в противном случае,

где Q 1 , ..., Q M являются взаимоисключающими предикатами (или φ (x 1 , ..., x n ) должны иметь значение, указанное в первом предложении, которое применяется), является примитивным рекурсивным в φ 1 , ... , φ M+1 , Q 1 , ..., Q M+1 .

- Стивен Клин, [ 3 ]

Kleene предоставляет доказательство этого с точки зрения логических рекурсивных функций «sg-of» sg () и «не признака» ~ sg () (Kleene 1952: 222-223); Первый возвращает 1, если его вход является положительным и -1, если его вход отрицательный.

Boolos-Burgess-Jeffrey делает дополнительное наблюдение, что «определение по случаям» должно быть как взаимоисключающим, так и коллективным исчерпывающим . Они также предлагают доказательство примитивной рекурсивности этой функции (Boolos-Burgess-Jeffrey 2002: 74-75).

If-then-else является основой формализма McCarthy : его использование заменяет как примитивную рекурсию, так и MU-оператор .

Самые ранние компиляторы Fortran поддержали вычислимый оператор GOTO для многоподобного ветвления. Ранние компиляторы Algol поддерживали тип данных переключения, который содержит список «обозначенных выражений». Оператор GOTO может ссылаться на переменную коммутатора и, предоставляя индекс, ветвь в нужное место. С опытом было понято, что необходима более формальная многопользовательская конструкция с единственной точкой входа и выхода. Такие языки, как BCPL , Algol-W и Algol-68 , внедрили формы этой конструкции, которые выжили через современные языки.

Типичный синтаксис

[ редактировать ]

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

  • первый selectс последующим выражением, которое часто называют управляющим выражением или управляющей переменной операции переключателя
  • Последующие строки, определяющие фактические случаи (значения), с соответствующими последовательностями операторов для выполнения, когда происходит совпадение
  • На языках с поведением в осеннее break Заявление обычно следует case Заявление о прекращении указанного заявления. [Уэллс]
  • На некоторых языках, например, PL/I , управляющее выражение является необязательным; Если нет контрольного выражения, то каждая альтернатива начинается с WHEN Пункт, содержащий логическое выражение и совпадение, происходит для первого случая, для которого это выражение оценивается в True. Это использование аналогично структурам if/then/elseif/else на некоторых других языках, например, perl .
  • На некоторых языках, например, REXX , контрольное выражение не допускается, и каждая альтернатива начинается с WHEN Пункт, содержащий логическое выражение и совпадение, происходит для первого случая, для которого это выражение оценивается в True.

Каждая альтернатива начинается с конкретного значения или списка значений (см. Ниже), что управляющая переменная может соответствовать и которая приведет к тому, что элемент управления затронет соответствующую последовательность операторов. Значение (или список/диапазон значений) обычно отделяется от соответствующей последовательности операций толстой кишкой или со стрелкой для значения. На многих языках каждому случаю также должно предшествовать ключевое слово, такое как case или when.

Необязательный случай по умолчанию обычно также разрешен, указанный default, otherwise, или else ключевое слово. Это выполняется, когда ни один из других случаев не соответствует управляющему выражению. На некоторых языках, таких как C, если ни один случай не совпадает и default опускается switch Заявление просто ничего не делает. В других, как PL/I, возникает ошибка.

Семантика

[ редактировать ]

Семантически, существует две основные формы операторов переключения.

Первая форма - это структурированные переключатели, как в Паскале, где занимается ровно одна ветвь, а случаи рассматриваются как отдельные, исключительные блоки. if -then -else Это функционирует как обобщенное условие , здесь с каким -либо количеством ветвей, а не только двумя.

Вторая форма - это неструктурированные переключатели, как в C, где случаи рассматриваются как этикетки в одном блоке, а коммутатор функционирует как обобщенное Goto. Это различие называется лечением осеннего, которое разрабатывается ниже.

Во многих языках выполняется только соответствующий блок, а затем выполнение продолжается в конце оператора Switch. К ним относятся семейство Паскаля (объект Pascal, Modula, Oberon, ADA и т. Д.), А также PL/I , современные формы FORTRAN и основные диалекты, на которые влияют Pascal, большинство функциональных языков и многие другие. Чтобы позволить нескольким значениям выполнять один и тот же код (и избегать необходимости дублировать код ), языки типа Паскаля позволяют любому количеству значений в случае, указанном в виде списка, разделенного запятыми, в виде диапазона или в качестве комбинации.

Языки, полученные из языка C, и, в целом, под влиянием вычисленного Goto Fortran , вместо этого функционируют падение, где управление перемещается в случай сопоставления, а затем выполнение продолжается («падает») к утверждениям, связанным со следующим случаем в исходном тексте Полем Это также позволяет нескольким значениям соответствовать одной и той же точке без какого -либо специального синтаксиса: они только что перечислены с пустыми телами. Значения могут быть специальными обусловленными с кодом в корпусе случая. На практике, осеннее обычно предотвращается break Ключевое слово в конце соответствующего тела, которое выходит из выполнения блока коммутатора, но это может вызвать ошибки из -за непреднамеренного падения, если программист забудет вставить break заявление. Таким образом, это видно многими [ 4 ] Как языковая бородавка и предупреждая в некоторых инструментах с ворсом. Синтаксически, случаи интерпретируются как метки, а не блоки, а операторы переключения и разрыва явно изменяют поток управления. Некоторые языки под влиянием C, такие как JavaScript , сохраняют по умолчанию падение, в то время как другие удаляют падение или разрешают его только в особых обстоятельствах. Примечательные вариации этого в семействе C включают C# , в котором все блоки должны быть прекращены с помощью break или return Если блок не пуст (то есть осеннее используется как способ указать несколько значений).

В некоторых случаях языки обеспечивают дополнительное падение. Например, Perl не пропадает по умолчанию, но случай может явно сделать это, используя continue ключевое слово. Это предотвращает непреднамеренное падение, но позволяет ему при желании. Точно так же BASH по умолчанию не проваливаться при прекращении ;;, но допускает падение [ 5 ] с ;& или ;;& вместо.

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

Компиляция

[ редактировать ]

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

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

Преимущества и недостатки

[ редактировать ]

В некоторых языках и средах программирования использование case или switch Заявление считается превосходящим эквивалентную серию IF ESE ESLE, если это если: это:

  • Легче отладки (например, установление точек останова на коде и таблице вызовов, если у отладчика нет условной возможности точки останова)
  • Проще для прочтения
  • Легче понять и, следовательно, легче поддерживать
  • Фиксированная глубина: последовательность операторов «если даже если» может дать глубокое гнездование, что затрудняет компиляцию (особенно в автоматически сгенерированном коде)
  • Легче убедиться, что все значения обрабатываются. Компиляторы могут выпустить предупреждение, если некоторые значения перечисления не обрабатываются.

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

С точки зрения графика управления , оператор переключателя состоит из двух узлов (вход и выход), а также один край между ними для каждой опции. В отличие от этого, последовательность «если ... иначе, если ... если», если », имеет дополнительный узел для каждого случая, кроме первого и последнего, вместе с соответствующим преимуществом. Полученный график управления потоком для последовательностей «если» S, таким образом, имеет гораздо больше узлов и почти вдвое больше ребра, при этом они не добавляют какую-либо полезную информацию. Тем не менее, простые ветви в операторах IF индивидуально концептуально проще, чем сложная ветвь оператора коммутатора. С точки зрения цикломатической сложности , оба эти варианты увеличивают его на k -1, если приведены k случаи .

Переключение выражений

[ редактировать ]

Выражения Switch представлены в Java SE 12 , 19 марта 2019 года в качестве предварительного просмотра. Здесь выражение целого переключателя можно использовать для возврата значения. Существует также новая форма этикетки, case L-> где правая сторона является единственным выражением. Это также предотвращает падение и требует, чтобы случаи были исчерпывающими. В Java SE 13 yield Заявление представлено, и в Java SE 14 выражения переключателя становятся стандартной языковой функцией. [ 8 ] [ 9 ] [ 10 ] Например:

int ndays = switch (month) {
    case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> 31;
    case APR, JUN, SEP, NOV -> 30;
    case FEB -> {
        if (year % 400 == 0) yield 29;
        else if (year % 100 == 0) yield 28;
        else if (year % 4 == 0) yield 29;
        else yield 28; }
};

Альтернативное использование

[ редактировать ]

Многие языки оценивают выражения внутри switch Блоки во время выполнения, позволяя нескольким менее очевидным применению для конструкции. Это запрещает определенные оптимизации компилятора, поэтому чаще встречается на языках динамических и сценариев, где повышенная гибкость более важна, чем накладные расходы на производительность.

Например, в PHP может использоваться константа в качестве «переменной», и будет выполнено первое утверждение, которое оценивается в эту константу:

switch (true) {
    case ($x == 'hello'):
        foo();
        break;
    case ($z == 'howdy'): break;
}
switch (5) {
    case $x: break;
    case $y: break;
}

Эта функция также полезна для проверки нескольких переменных по одному значению, а не одной переменной по многим значениям. COBOL также поддерживает эту форму (и другие формы) в EVALUATE заявление. PL/I имеет альтернативную форму SELECT утверждение, где управляющее выражение вообще опущено, и первое WHEN Это оценивается в True, выполняется.

В Руби , из -за его обращения === Равенство, оператор может использоваться для тестирования для класса переменной:

case input
when Array then puts 'input is an Array!'
when Hash then puts 'input is a Hash!'
end

Руби также возвращает значение, которое может быть назначено переменной, и на самом деле не требует case иметь какие -либо параметры (действуя немного как else if заявление):

catfood =
  case
  when cat.age <= 1
    junior
  when cat.age > 10
    senior
  else
    normal
  end

Ассемблер

[ редактировать ]

Оператор переключения на языке сборки :

switch:
  cmp ah, 00h
  je a
  cmp ah, 01h
  je b
  jmp swtend   ; No cases match or "default" code here
a:
  push ah
  mov al, 'a'
  mov ah, 0Eh
  mov bh, 00h
  int 10h
  pop ah
  jmp swtend   ; Equivalent to "break"
b:
  push ah
  mov al, 'b'
  mov ah, 0Eh
  mov bh, 00h
  int 10h
  pop ah
  jmp swtend   ; Equivalent to "break"
  ...
swtend:

Для Python 3.10.6 были приняты PEPS 634-636, что добавило match и case ключевые слова. [ 11 ] [ 12 ] [ 13 ] [ 14 ] В отличие от других языков, Python, в частности, не демонстрирует осеннего поведения.

letter = input("Put in a single letter: ").strip()[0].casefold() # first non-whitespace character of the input, lowercase
match letter:
    case 'a' | 'e' | 'i' | 'o' | 'u': # Unlike conditions in if statements, the `or` keyword cannot be used here to differentiate between cases
        print(f"Letter {letter} is a vowel!")
    case 'y':
        print(f"Letter {letter} may be a vowel.")
    case _: # `case _` is equivalent to `default` from C and others
        print(f"Letter {letter} is not a vowel!")

Обработка исключений

[ редактировать ]

Ряд языков реализует форму оператора коммутатора при обработке исключений , когда, если исключение поднимается в блоке, выбирается отдельная ветвь, в зависимости от исключения. В некоторых случаях также присутствует филиал по умолчанию, если нет исключения, также присутствует. Ранним примером является Modula-3 , который использует TRY... EXCEPT Синтаксис, где каждый EXCEPT определяет случай. Это также встречается в Delphi , Scala и Visual Basic .net .

Альтернативы

[ редактировать ]

Некоторые альтернативы операторам переключения могут быть:

  • Серия IF-ELSE условий , которые изучают целевое значение за раз. Поведение осеннего поведения может быть достигнуто с помощью последовательности условий , каждая из которых без предложения без других .
  • Таблица поиска , которая содержит, как ключи, case значения и, как значения, часть под case заявление.
(На некоторых языках только фактические типы данных разрешены в виде значений в таблице поиска. На других языках также можно назначить функции в виде значений таблицы поиска, набирая ту же гибкость, что и реальная switch заявление. См. Статью о управлении таблицей для более подробной информации об этом).
Lua не поддерживает операторы Case/Switch. [ 15 ] Эта техника поиска является одним из способов реализации switch заявления на языке Lua, у которого нет встроенных switch. [ 15 ]
В некоторых случаях таблицы поиска более эффективны, чем не оптимизированные switch Операторы, поскольку многие языки могут оптимизировать поиск таблиц, тогда как операторы коммутатора не оптимизированы, если только диапазон значений не является небольшим с небольшим количеством пробелов. Неоптимизированный, не бинарный поиск , однако, почти наверняка будет медленнее, чем не оптимизированный переключатель или эквивалентные множественные операторы IF-ELSE . [ Цитация необходима ]
  • Таблица управления (которая может быть реализована в виде простой таблицы поиска) также может быть настроена для размещения нескольких условий на нескольких входах, если это необходимо, и обычно демонстрирует большую «визуальную компактность», чем эквивалентный переключатель (который может занимать много операторов).
  • Сопоставление рисунков , которое используется для реализации функциональности, подобной коммутатору, на многих функциональных языках.

Смотрите также

[ редактировать ]
  1. ^ Скит, Джон (23 марта 2019 г.). C# в глубине . Мэннинг. ISBN  978-1617294532 .
  2. ^ Блох, Джошуа (2018). «Эффективная Java: Руководство по языку программирования» (третье изд.). Аддисон-Уэсли. ISBN  978-0134685991 .
  3. ^ «Определение по случаям», Клин 1952: 229
  4. ^ van der Linden, Peter (1994). Эксперт C Программирование: Deep C Secrets , p. 38. Prentice Hall, Eaglewood Cliffs. ISBN   0131774298 .
  5. ^ Со времени версии 4.0 , выпущенной в 2009 году.
  6. ^ Влад Лазаренко. От оператора переключения до машинного кода
  7. ^ Гюнтерот, Курт (27 апреля 2016 г.). Оптимизированный C ++ . О'Рейли СМИ. п. 182. ISBN  9781491922033 .
  8. ^ «JEP 325: выключатели коммутатора (предварительный просмотр)» . OpenJdk.java.net . Получено 2021-04-28 .
  9. ^ «JEP 354: Выключатель Switch (второй предварительный просмотр)» . OpenJdk.java.net . Получено 2021-04-28 .
  10. ^ "JEP 361: выключение вывода" . OpenJdk.java.net . Получено 2021-04-28 .
  11. ^ Галиндо Сальгадо, Пабло. «Что нового в Python 3.10» . Python 3.10.6 Документация . Получено 2022-08-19 .
  12. ^ Бухер, Брандт; Ван Россум, Гвидо (2020-09-12). «PEP 634 - Структурное сопоставление рисунков: спецификация» . Предложения по улучшению питона . Получено 2022-08-19 .
  13. ^ Кон, Тобиас ; Ван Россум, Гвидо (2020-09-12). «PEP 635 - Структурное соответствие рисунков: мотивация и обоснование» . Предложения по улучшению питона . Получено 2022-08-19 .
  14. ^ Моиссет, Даниэль Ф. "PEP 636 - Структурное соответствие рисунка: учебник" . Предложения по улучшению питона . Получено 2022-08-19 .
  15. ^ Jump up to: а беременный Оператор переключения в Lua

Дальнейшее чтение

[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 767d679ccb759864a0917170fb6fa098__1725128700
URL1:https://arc.ask3.ru/arc/aa/76/98/767d679ccb759864a0917170fb6fa098.html
Заголовок, (Title) документа по адресу, URL1:
Switch statement - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)