Команды и выражения case языка pl/sql на примерах

Поисковая команда CASE

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


CASE
WHEN выражение_1 THEN
команды_1
WHEN выражение_2 THEN
команда_2
...
ELSE
команды_else
END CASE;
Она идеально подходит для реализации логики начисления премии:
CASE
WHEN salary >= 10000 AND salary <=20000 THEN
give_bonus(employee_id, 1500);
WHEN salary > 20000 AND salary <= 40000 THEN
give_bonus(employee_id, 1000);
WHEN salary > 40000 THEN
give_bonus(employee_id, 500);
ELSE
give_bonus(employee_id, 0);
END CASE;

Поисковая команда , как и простая команда, подчиняется следующим правилам:

  • Выполнение команды заканчивается сразу же после выполнения последовательности исполняемых команд, связанных с истинным выражением. Если истинными оказываются несколько выражений, то выполняются команды, связанные с первым из них.
  • Ключевое слово не обязательно. Если оно не задано и ни одно из выражений не равно , инициируется исключение .
  • Условия проверяются в строго определенном порядке, от начала к концу.

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

CASE
WHEN salary > 40000 THEN
give_bonus(employee_id, 500);
WHEN salary > 20000 THEN
give_bonus(employee_id, 1000);
WHEN salary >= 10000 THEN
give_bonus(employee_id, 1500);
ELSE
give_bonus(employee_id, 0);
END CASE;

Если оклад некоего сотрудника равен 20 000, то первые два условия равны , а третье — , поэтому сотрудник получит премию в 1500 долларов. Если же оклад равен 21 000, то результат второго условия будет равен , и премия составит 1000 долларов. Выполнение команды завершится на второй ветви , а третье условие даже не будет проверяться. Стоит ли использовать такой подход при написании команд — вопрос спорный. Как бы то ни было, имейте в виду, что написать такую команду возможно, а при отладке и редактировании программ, в которых результат зависит от порядка следования выражений, необходима особая внимательность.

Логика, зависящая от порядка следования однородных ветвей , является потенциальным источником ошибок, возникающих при их перестановке. В качестве примера рассмотрим следующую поисковую команду , в которой при значении , равном 20 000, проверка условий в обеих ветвях дает : 

CASE
WHEN salary BETWEEN 10000 AND 20000 THEN
give_bonus(employee_id, 1500);
WHEN salary BETWEEN 20000 AND 40000 THEN
give_bonus(employee_id, 1000);
...

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

CASE
WHEN salary BETWEEN 20000 AND 40000 THEN
give_bonus(employee_id, 1000);
WHEN salary BETWEEN 10000 AND 20000 THEN
give_bonus(employee_id, 1500);
...

На первый взгляд все верно, не так ли? К сожалению, из-за перекрытия двух ветвей в программе появляется коварная ошибка. Теперь сотрудник с окладом 20 000 получит премию 1000 вместо положенных 1500. Возможно, в некоторых ситуациях перекрытие между ветвями желательно и все же его следует по возможности избегать. Всегда помните, что порядок следования ветвей важен, и сдерживайте желание доработать уже работающий код — «не чините то, что не сломано».

Поскольку условия проверяются по порядку, можно немного повысить эффективность кода, поместив ветви с наиболее вероятными условиями в начало списка. Кроме того, если у вас есть ветвь с «затратными» выражениями (например, требующими значительного процессорного времени и памяти), их можно поместить в конец, чтобы свести к минимуму вероятность их проверки. За подробностями обращайтесь к разделу «Вложенные команды ».

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

Оператор if

Для организации условного ветвления язык C# унаследовал от С и С++ конструкцию if…else. Ее синтаксис должен быть интуитивно понятен для любого, кто программировал на процедурных языках:

if (условие)   оператор (операторы) else   оператор (операторы)

Если по каждому из условий нужно выполнить более одного оператора, эти операторы должны быть объединены в блок с помощью фигурных скобок {…}. (Это также касается других конструкций C#, в которых операторы могут быть объединены в блок — таких как циклы for и while.)

Стоит обратить внимание, что в отличие от языков С и С++, в C# условный оператор if может работать только с булевскими выражениями, но не с произвольными значениями вроде -1 и 0. В операторе if могут применяться сложные выражения, и он может содержать операторы else, обеспечивая выполнение более сложных проверок

Синтаксис похож на применяемый в аналогичных ситуациях в языках С (С++) и Java. При построении сложных выражений в C# используется вполне ожидаемый набор логических операторов. Давайте рассмотрим следующий пример:

В операторе if могут применяться сложные выражения, и он может содержать операторы else, обеспечивая выполнение более сложных проверок. Синтаксис похож на применяемый в аналогичных ситуациях в языках С (С++) и Java. При построении сложных выражений в C# используется вполне ожидаемый набор логических операторов. Давайте рассмотрим следующий пример:

Как видите количество else if, добавляемых к единственному if, не ограничено. Один момент, который следует отметить касательно if: фигурные скобки применять не обязательно, если в условной ветви присутствует только один оператор, как показано в исходном примере.

Раздел switchThe switch section

Оператор включает один или несколько разделов switch.A statement includes one or more switch sections. Каждый раздел switch содержит одну или несколько меток case (меток case или меток default), за которыми следует один или несколько операторов.Each switch section contains one or more case labels (either a case or default label) followed by one or more statements. Оператор может включать не более одной метки default в каждом разделе switch.The statement may include at most one default label placed in any switch section. В следующем примере показан простой оператор с тремя разделами switch, каждый из которых содержит два оператора.The following example shows a simple statement that has three switch sections, each containing two statements. Второй раздел switch содержит метки и .The second switch section contains the and labels.

Оператор может содержать любое количество разделов switch, а каждый раздел может иметь одну или несколько меток case (как показано в следующем примере).A statement can include any number of switch sections, and each section can have one or more case labels, as shown in the following example. Однако две метки case не могут содержать одно и то же выражение.However, no two case labels may contain the same expression.

Выполняет только раздел switch в операторе switch.Only one switch section in a switch statement executes. C# не позволяет продолжить выполнение следующего раздела switch после выполнения предыдущего.C# doesn’t allow execution to continue from one switch section to the next. Поэтому, например, следующий код вызовет ошибку компиляции CS0163: «Управление не может передаваться вниз от одной метки case к другой (<case label>)».Because of this, the following code generates a compiler error, CS0163: «Control cannot fall through from one case label (<case label>) to another.»

Обычно для соблюдения этого требования выполняется явный выход из раздела switch с использованием оператора break, goto или return.This requirement is usually met by explicitly exiting the switch section by using a break, goto, or return statement. При этом допустим также приведенный ниже код, так как он гарантирует, что управление программой не будет передано дальше, в раздел switch .However, the following code is also valid, because it ensures that program control can’t fall through to the switch section.

Выполнение списка операторов в разделе switch с меткой case, соответствующей выражению сопоставления, начинается с первого оператора и продолжается по списку, обычно до достижения оператора перехода, такого как , , , или .Execution of the statement list in the switch section with a case label that matches the match expression begins with the first statement and proceeds through the statement list, typically until a jump statement, such as a , , , , or , is reached. В этой точке управление передается за пределы оператора или к другой метке case.At that point, control is transferred outside the statement or to another case label. Оператор , если он используется, должен передать управление константе типа метки.A statement, if it’s used, must transfer control to a constant label. Это ограничение является обязательным, поскольку попытка передачи управления переменной типа метки может иметь нежелательные побочные эффекты, такие передача управления в непредусмотренное расположение в коде или создание бесконечного цикла.This restriction is necessary, since attempting to transfer control to a non-constant label can have undesirable side-effects, such transferring control to an unintended location in code or creating an endless loop.

Представляем switch-выражения!

Как я показал в начале статьи, начиная с Java 12 и выше, вы можете решить вышеуказанную проблему следующим образом:

Я думаю, что это довольно очевидно: если равен , то ‘у будет присвоено (иными словами превращается в ). становится .

Сразу возникают две мысли:

  • может иметь результат;
  • что там со стрелками?

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

Выражение или оператор

Возможно, вы удивлены, что switch теперь является выражением. А чем же он был до этого?

До Java 12 switch был оператором — императивной конструкцией, регулирующей поток управления.

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

Разница в том, что просто выполняет соответствующий блок, тогда как тернарный оператор возвращает какой-то результат:

То же самое для switch: до Java 12, если вы хотели вычислить значение и сохранить результат, то должны были либо присвоить его переменной (а затем ), либо вернуть из метода, созданного специально для оператора .

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


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

Стрелка или двоеточие

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

Важно понимать, что для этого не обязательно использовать в качестве выражения. Фактически, пример ниже эквивалентен приведенному в начале статьи коду:

Обратите внимание, что теперь вы можете использовать со значением! Это идеально согласуется с инструкциями старого стиля, которые используют без какого-либо значения. Так в каком случае стрелка означает выражение вместо оператора, для чего она здесь? Просто хипстерский синтаксис?. Исторически сложилось, что метки с двоеточием просто отмечают точку входа в блок операторов

С этого места начинается выполнение всего кода ниже, даже когда встречается другая метка. В нам это известно, как сквозной переход к следующему (fall-through): метка определяет, куда перепрыгивает поток управления. Для его завершения нужен или

Исторически сложилось, что метки с двоеточием просто отмечают точку входа в блок операторов. С этого места начинается выполнение всего кода ниже, даже когда встречается другая метка. В нам это известно, как сквозной переход к следующему (fall-through): метка определяет, куда перепрыгивает поток управления. Для его завершения нужен или .

В свою очередь, использование стрелки означает, что будет выполнен только блок справа от нее. И никакого «проваливания».

Условный оператор if

Условный оператор if может использоваться в форме полной или неполной развилки.

Неполная развилка Полная развилка

1234

if (Условие){  БлокОпераций1;}

12345678

if (Условие){  БлокОпераций1;}else{  БлокОпераций2;}

В случае неполной развилки если Условие истинно, то БлокОпераций1 выполняется, если Условие ложно, то БлокОпераций1 не выполняется. В случае полной развилки если Условие истинно, то выполняется БлокОпераций1, иначе выполняется БлокОпераций2.БлокОпераций может состоять из одной операции. В этом случае наличие фигурных скобок, ограничивающих блок, необязательно. Основными операциями, проверяемыми внутри условного блока, являются операции отношения.Пример на C:

1234567891011121314

#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf#include <stdio.h>int main(){  int k;           // объявляем целую переменную k  printf(«k= «);   // выводим сообщение  scanf(«%d», &k); // вводим переменную k  if (k >= 5)      // если k>5    printf(«%d >= 5», k); // выводим «ЗНАЧЕНИЕ >= 5»  else             // иначе    printf(«%d < 5», k);  // выводим «ЗНАЧЕНИЕ < 5»  getchar(); getchar();  return 0;}

123456789101112131415161718

#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf#include <stdio.h>#include <stdlib.h> // для использования функции systemint main() {  int key;  // объявляем целую переменную key  system(«chcp 1251»); // переходим в консоли на русский язык  system(«cls»);       // очищаем окно консоли  printf(«Введите номер пункта, 1 или 2: «);  scanf(«%d», &key);   // вводим значение переменной key  if (key == 1)        // если key = 1    printf(«\n Выбран первый пункт»); // выводим сообщение  else if (key == 2)   // иначе если key = 2    printf(«\n Выбран второй пункт»); // выводим сообщение  else                 // иначе    printf(«\n Первый и второй пункты не выбраны»); // выводим сообщение  getchar(); getchar();  return 0;}

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

123456789101112131415161718

#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf#include <stdio.h>#include <stdlib.h> // для использования функции systemint main() {  int key;  // объявляем целую переменную key  system(«chcp 1251»); // переходим в консоли на русский язык  system(«cls»);       // очищаем окно консоли  printf(«Введите номер пункта, 1 или 2: «);  scanf(«%d», &key);   // вводим значение переменной key  if (key != 1) {      // если key не равен 1    if (key == 2)    // если key равен 2      printf(«\n Выбран второй пункт»); // вывод сообщения  }              // если key — не 1 и не 2, то ничего не выводится  else // иначе, если key равен 1    printf(«\n Выбран первый пункт»); // вывод сообщения  getchar(); getchar();  return 0;}

Простые команды CASE

Простая команда позволяет выбрать для выполнения одну из нескольких последовательностей команд PL/SQL в зависимости от результата вычисления выражения. Он записывается следующим образом:

CASE выражение
WHEN результат_1 THEN
команды_1
WHEN результат_2 THEN
команды_2
...
ELSE
команды_else
END CASE; 

Ветвь здесь не обязательна. При выполнении такой команды PL/SQL сначала вычисляет выражение, после чего результат сравнивается с . Если они совпадают, то выполняются . В противном случае проверяется значение результат_2 и т. д.

Приведем пример простой команды , в котором премия начисляется в зависимости от значения переменной : 

CASE employee_type
WHEN 'S' THEN
award_salary_bonus(employee_id);
WHEN 'H' THEN
award_hourly_bonus(employee_id);
WHEN 'C' THEN
award_commissioned_bonus(employee_id);
ELSE
RAISE invalid_employee_type;
END CASE;

В этом примере присутствует явно заданная секция , однако в общем случае она не обязательна. Без секции компилятор PL/SQL неявно подставляет такой код:

ELSE
RAISE CASE_NOT_FOUND; 

Иначе говоря, если не задать ключевое слово и если никакой из результатов в секциях не соответствует результату выражения в команде , PL/SQL инициирует исключение . В этом и заключается отличие данной команды от . Когда в команде отсутствует ключевое слово , то при невыполнении условия не происходит ничего, тогда как в команде аналогичная ситуация приводит к ошибке.

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

CASE TRUE
WHEN salary >= 10000 AND salary <=20000
THEN
give_bonus(employee_id, 1500);
WHEN salary > 20000 AND salary <= 40000
THEN
give_bonus(employee_id, 1000);
WHEN salary > 40000
THEN
give_bonus(employee_id, 500);
ELSE
give_bonus(employee_id, 0);
END CASE;

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

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

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

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


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

Пример

Рассмотрим пример, который показывает, как использовать оператор CASE в MySQL. Во-первых, мы рассмотрим первый синтаксис для оператора CASE. Например:

MySQL

DELIMITER //

CREATE FUNCTION CostLevel ( monthly_value INT ) RETURNS varchar(20)

BEGIN

DECLARE cost_level varchar(20);

CASE monthly_value WHEN 3000 THEN SET cost_level = ‘Low Cost’;

WHEN 4000 THEN SET cost_level = ‘Avg Cost’;

ELSE SET cost_level = ‘High Cost’; END CASE;

RETURN cost_level;

END; //

DELIMITER ;

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

DELIMITER//  

CREATE FUNCTIONCostLevel(monthly_valueINT)

RETURNSvarchar(20)   BEGIN  

DECLAREcost_levelvarchar(20);  

CASEmonthly_value

WHEN3000THEN

SETcost_level=’Low Cost’;  

WHEN4000THEN

SETcost_level=’Avg Cost’;  

ELSE

SETcost_level=’High Cost’;

END CASE;  

RETURNcost_level;  

END;//  

DELIMITER;

В этом примере мы использовали первый синтаксис оператора CASE. Если значение month_value будет равно 3000, тогда для cost_level будет установлено значение ‘Low Cost’. Если значение month_value будет равно 4000, то для cost_level будет установлено значение ‘Avg Cost’. В противном случае cost_level достигнет ‘High Cost’. Теперь рассмотрим использование оператор CASE со вторым синтаксисом.

MySQL

DELIMITER //

CREATE FUNCTION CostLevel ( monthly_value INT ) RETURNS varchar(20)

BEGIN

DECLARE cost_level varchar(20);

CASE WHEN monthly_value <= 3000 THEN SET cost_level = ‘Low cost’;

WHEN monthly_value > 3000 AND monthly_value <= 6000 THEN SET cost_level = ‘Avg cost’;

ELSE SET cost_level = ‘High cost’; END CASE;

RETURN cost_level;

END; //

DELIMITER ;

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

DELIMITER//  

CREATE FUNCTIONCostLevel(monthly_valueINT)

RETURNSvarchar(20)   BEGIN  

DECLAREcost_levelvarchar(20);  

CASE

WHENmonthly_value<=3000THEN

SETcost_level=’Low cost’;  

WHENmonthly_value>3000ANDmonthly_value<=6000THEN

SETcost_level=’Avg cost’;  

ELSE

SETcost_level=’High cost’;

END CASE;  

RETURNcost_level;  

END;//  

DELIMITER;

В этом примере мы используем второй синтаксис для оператора CASE. В этом примере, если значение month_value меньше или равно 3000, тогда переменной cost_level будет присвоено ‘Low cost’. Если значение month_value больше 3000 и меньше или равно 6000, тогда cost_level будет присвоено значение ‘Avg cost’. В противном случае cost_level будет присвоено значение ‘High cost’.

Оператор Switch

Рассмотрим пример из темы «ветвления». Программа выводит название дня недели по порядковому номера

#include<conio.h>
#include<stdio.h>

int main() {
	unsigned day;

	printf("Enter day ");
	scanf("%d", &day);

	if (day > 7) {
		day = day % 7;
	}

	if (day == 0) {
		printf("Sunday");
	} else if (day == 1) {
		printf("Monday");
	} else if (day == 2) {
		printf("Tuesday");
	} else if (day == 3) {
		printf("Wednesday");
	} else if (day == 4) {
		printf("Thursday");
	} else if (day == 5) {
		printf("Friday");
	} else if (day == 6) {
		printf("Saturday");
	} 

	getch();
}

Этот код состоит из семи идущих друг за другом операторов if. Его код можно упростить с помощью оператора switch

#include<conio.h>
#include<stdio.h>

int main() {
	unsigned day;

	printf("Enter day ");
	scanf("%d", &day);

	if (day > 7) {
		day = day % 7;
	}

	switch (day) {
	case 0:
		printf("Sunday");
		break;
	case 1:
		printf("Monday");
		break;
	case 2:
		printf("Tuesday");
		break;
	case 3:
		printf("Wednesday");
		break;
	case 4:
		printf("Thursday");
		break;
	case 5:
		printf("Friday");
		break;
	default:
		printf("Saturday");
	}

	getch();
}

Оператор switch принимает в качестве аргумента число, и в зависимости от его значения выполняет те или иные команды.

switch (<переменная>) {
	case <значение 1>:
		<ветвь 1>
	
	
}

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


В примере выше каждая ветвь оканчивается оператором break

Это важно. Когда компьютер видит оператор break, он выходит из оператора switch

Если бы он отсутствовал, то программа «провалилась» бы дальше, и стала выполнять следующие ветви.

#include<conio.h>
#include<stdio.h>

int main() {
	unsigned day;

	printf("Enter day ");
	scanf("%d", &day);

	if (day > 7) {
		day = day % 7;
	}

	switch (day) {
	case 0:
		printf("Sunday");
	case 1:
		printf("Monday");
	case 2:
		printf("Tuesday");
	case 3:
		printf("Wednesday");
	case 4:
		printf("Thursday");
	case 5:
		printf("Friday");
	default:
		printf("Saturday");
	}

	getch();
}

Введите значение, например 3, и вы увидите, что программа выведет

WednesdayThursdayFridaySaturday

то есть все ветви, после найденной.

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

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
	float a, b, c;
	char op;

	scanf("%f %c %f", &a, &op, &b);
	switch (op) {
		case '+': {
			c = a + b;
			break;
		}
		case '-': {
			c = a - b;
			break;
		}
		case '/': {
			if (b != 0.0) {
				c = a / b;
			} else {
				printf("Error: divide by zero");
				getch();
				exit(1);
			}
			break;
		}
		case '*': {
			c = a * b;
			break;
		}
		default:
			printf("No operation defined");
			getch();
			exit(1);
	}

	printf("%.6f", c);
	getch();
}

Если ввести

1 + 2

то будет выведен результат операции 1 + 2 = 3

Хочу обратить внимание, что литеры типа ‘+’ и т.п. воспринимаются в качестве чисел, поэтому их можно использовать в операторе switch

В этой программе использовалась функция exit из библиотеки stdlib. Функция останавливает работу программы и возвращает результат её работы. Если возвращается истина (ненулевое значение), то это значит, что программа была выполнена с ошибкой.

Ветвь default может располагаться в любом месте, не обязательно в конце. Этот код также будет нормально работать

    switch (day) {
    case 0:
        printf("Sunday");
        break;
    case 1:
        printf("Monday");
        break;
    case 2:
        printf("Tuesday");
        break;
    case 3:
        printf("Wednesday");
        break;
    case 4:
        printf("Thursday");
        break;
	default:
        printf("Saturday");
		break;
    case 5:
        printf("Friday");
        break;
    }

default здесь также нуждается в операторе break, как и другие ветви, иначе произойдёт сваливание вниз. Несмотря на то, что так можно писать, это плохой стиль программирования. Ветвь default логически располагается в конце, когда других вариантов больше нет.

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

#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
 
int main() {
//Это, конечно, константа, но не может быть использована как
//значение для оператора switch
	const int monday = 0;
    unsigned day;
 
    printf("Enter day ");
    scanf("%d", &day);
 
    if (day > 7) {
        day = day % 7;
    }
 
    switch (day) {
    case monday:
        printf("Sunday");
        break;
    case 1:
        printf("Monday");
        break;
    case 2:
        printf("Tuesday");
        break;
    case 3:
        printf("Wednesday");
        break;
    case 4:
        printf("Thursday");
        break;
	default:
        printf("Saturday");
		break;
    case 5:
        printf("Friday");
        break;
    }
 
    getch();
}

Q&A

Всё ещё не понятно? – пиши вопросы на ящик

Синтаксис

Синтаксис оператора CASE в SQL Server (Transact-SQL):

CASE expression

WHEN value_1 THEN result_1 WHEN value_2 THEN result_2 … WHEN value_n THEN result_n

ELSE result

END

ИЛИ

CASE

WHEN condition_1 THEN result_1 WHEN condition_2 THEN result_2 … WHEN condition_n THEN result_n

ELSE result

END

Параметры или аргументы

expression — выражение, которое будет сравниваться с каждым из предоставленных значений. (то есть: value_1, value_2, … value_n).value_1, value_2, … value_n — значения, которые будут сравниваться. Значения сравниваются в указанном порядке. Когда value соответствует expression, оператор CASE выполнит указанные команды и не будет дальше сравнивать value.condition_1, condition_2, … condition_n — условия, которые будут сравниваться. Условия сравниваются в указанном порядке. Как только условие окажется истинным, оператор CASE вернет результат и не будет сравнивать условия дальше. Все условия должны быть одного и того же типа.result_1, result_2, … result_n – возвращаемые значение после того, как условие установлено как true. Все значения должны быть одного типа данных.

Условные конструкции

Последнее обновление: 30.07.2016

Условные конструкции — один из базовых компонентов многих языков программирования, которые направляют работу программы по одному из путей в зависимости от определенных условий.

В языке C# используются следующие условные конструкции: и

Конструкция if/else

Конструкция if/else проверяет истинность некоторого условия и в зависимости от результатов проверки выполняет определенный код:

int num1 = 8;
int num2 = 6;
if(num1 > num2)
{
	Console.WriteLine($"Число {num1} больше числа {num2}");
}

После ключевого слова ставится условие. И если это условие выполняется, то срабатывает код, который помещен далее в блоке if после фигурных скобок. В качестве условий выступают ранее рассмотренные операции сравнения.

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

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

int num1 = 8;
int num2 = 6;
if(num1 > num2)
{
	Console.WriteLine($"Число {num1} больше числа {num2}");
}
else
{
	Console.WriteLine($"Число {num1} меньше числа {num2}");
}

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

int num1 = 8;
int num2 = 6;
if(num1 > num2)
{
	Console.WriteLine($"Число {num1} больше числа {num2}");
}
else if (num1 < num2)
{
    Console.WriteLine($"Число {num1} меньше числа {num2}");
}
else
{
    Console.WriteLine("Число num1 равно числу num2");
}

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

int num1 = 8;
int num2 = 6;
if(num1 > num2 && num1==8)
{
	Console.WriteLine($"Число {num1} больше числа {num2}");
}

В данном случае блок if будет выполняться, если равно и равно .

Конструкция switch

Конструкция switch/case аналогична конструкции , так как позволяет обработать сразу несколько условий:

Console.WriteLine("Нажмите Y или N");
string selection = Console.ReadLine();
switch (selection)
{
    case "Y":
        Console.WriteLine("Вы нажали букву Y");
        break;
    case "N":
        Console.WriteLine("Вы нажали букву N");
        break;
    default:
        Console.WriteLine("Вы нажали неизвестную букву");
        break;
}

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

В конце каждого блока сase должен ставиться один из операторов перехода: break, goto case, return или throw. Как правило, используется оператор break. При его применении другие блоки выполняться не будут.

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

int number = 1;
switch (number)
{
    case 1:
        Console.WriteLine("case 1");
        goto case 5; // переход к case 5
    case 3:
        Console.WriteLine("case 3");
        break;
    case 5:
        Console.WriteLine("case 5");
        break;
	default:
        Console.WriteLine("default");
        break;
}

Если мы хотим также обработать ситуацию, когда совпадения не будет найдено, то можно добавить блок default, как в примере выше.

Применение оператора позволит выйти не только из блока case, но и из вызывающего метода. То есть, если в методе Main после конструкции switch..case, в которой используется оператор , идут какие-либо операторы и выражения, то они выполняться не будут, а метод Main завершит работу.

Оператор применяется для выброса ошибок и будет рассмотрен в одной из следующим тем.

Тернарная операция

Тернарную операция имеет следующий синтаксис: . Здесь сразу три операнда. В зависимости от условия тернарная операция возвращает второй или третий операнд: если условие равно , то возвращается второй операнд; если условие равно , то третий. Например:

int x=3;
int y=2;
Console.WriteLine("Нажмите + или -");
string selection = Console.ReadLine();

int z = selection=="+"? (x+y) : (x-y);
Console.WriteLine(z);

Здесь результатом тернарной операции является переменная z. Если мы выше вводим «+», то z будет равно второму операнду — (x+y). Иначе z будет равно третьему операнду.

НазадВперед

case

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

Перед началом исполнения тела (содержимое между фигурными скобками) оператора , переменная указанная в скобках, должна быть инициализирована каким-нибудь значением, поскольку это значение будет сравниваться со значениями, указанными после case. Инструкции, расположенные после , будут исполняться до тех пор, пока не встретится оператор .

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

Итого

  • Используйте оператор при числе ветвлений более двух, чтобы не загромождать if-структурами код.
  • Не забывайте завершать логический блок каждой ветки соответствующего конкретному значению (блок case) вызовом .
  • Оператор switch помимо некоторых примитивных типов, в качестве выражения может использовать также типы и .
  • Помните про блок – употребляйте его для обработки незапланированных значений выбора.
  • Для оптимизации производительности переместите ветки кода с наиболее часто встречающимися вариантами выбора к началу блока switch.
  • Не увлекайтесь «оптимизацией» за счёт удаления в конце блока выбора – такой код сложен для понимания, и, как следствие, тяжело сопровождать при его развитии.

С этим читают