Case of что значит эта ошибка

Помимо условного оператора If в языке программирования Pascal существует оператор выбора Case of. Рассмотрим его применение на примере программы, которая выводит на экран то или иное сообщение, в зависимости от введенного числа.

Вывод сообщения на экран с помощью If.


program vetvlenija7;
uses crt;
var NUM :integer;
begin
clrscr;
writeln(‘Введите число от 1 до 4:’);
readln (NUM);
if NUM=0 then
writeln (‘Нуль’);
if NUM=1 then
writeln (‘Один’);
if NUM=2 then
writeln (‘Два’)
if NUM=3 then
writeln (‘Три’)
if NUM=4 then
writeln (‘Четыре’);
readln
end.

Эта программа выводит на экран сообщение (Нуль, Один и т. д.) в зависимости от того какое мы введем число. Однако, ту же задачу можно выполнить более простым способом с помощью оператора Case of.

Использование Case Of.


program vetvlenija7;
uses crt;
var NUM :integer;
begin
clrscr;
writeln(‘Введите число от 0 до 4:’);
readln (NUM);
case NUM of
0:writeln (‘Нуль’);
1:writeln (‘Один’);
2:writeln (‘Два’);
3:writeln (‘Три’);
4:writeln (‘Четыре’);
end;
readln
end.

В строке №8 записывается оператор выбора Case Of. Сначала записывается слово Case, затем записывается переменная, затем слово Of. После служебного слова Of идет перечисление всех возможных значений переменной (строка №9 — №13), а через двоеточие указывается действие, которое нужно сделать, если переменная принимает то или иное значение. Таким образом, если мы вводим с клавиатуры 0, то на экран выводится сообщение «Нуль» (строка №9), если вводим 1, то выводится сообщение «Один» (строка №10) и т.д.

Нам не нужно каждый раз писать конструкцию If…Then.
Достаточно указать CASE «переменная» OF, а затем для каждого значения этой переменной через двоеточие прописать вывод на экран. После перечисления всех операторов необходимо поставить служебное слово End.

case of

Запустим программу и введем любое число от 0 до 4 (например, 4)

case of.

Запустим программу и введем любое число от 0 до 4 (например, 4)

case of.


Напишем программу, которая определяет квартал года по введенному числу месяца.

Использование Case Of Else.


program vetvlenija8;
uses crt;
var NUM :integer;
begin
clrscr;
write (‘Введите номер месяца’);
readln (NUM);
case NUM of
1,2,3: writeln (‘Первый квартал’);
4,5,6: writeln (‘Второй квартал’);
7,8,9: writeln (‘Третий квартал’);
10,11,12: writeln (‘Четвертый квартал’)
else
writeln (‘Вы неправильно указали месяц’)
end;
readln
end.

В строке №8 записываем оператор выбора Case Of. После слова Of (в строках №9 — №12) указываем возможные значения нашей переменной. Причем несколько значений можно указать в одной строке. Например, в строке №9 мы указываем 3 значения для переменной и действие, которое нужно совершить, если будут введены эти переменные. Т.е. если мы вводим с клавиатуры 1 или 2 или 3, то на экран выводится сообщение «Первый квартал».

В строке №13 записывается служебное слово Else. Если мы вводим с клавиатуры число, которое лежит вне диапазона чисел от 1 до 12, то должно совершиться действие, которое указывается после слова Else (строка №14).

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

case of else

case of else.

case of else.


Дополнение к материалу.

В данном примере вместо перечисления значений переменной можно использовать диапазон значений переменной. Например, строку №9 можно записать так: 1..3: writeln (‘Первый квартал’); Т.е. сначала указывается первое значение переменной, а затем через 2 точки указывается последнее значение переменной.


Следующая статья : Циклы в Паскаль.


Maria Shakun

0 / 0 / 0

Регистрация: 09.03.2016

Сообщений: 5

1

09.03.2016, 23:54. Показов 5464. Ответов 11

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Доброго времени суток! Ребят, такая тема: в C++ начала изучать операторы switch, case. И вот у меня заступорилась программа: на case ’10’ выдает ошибку. Например, когда единицу убираешь, оставляя только нуль, он ловит ошибку на case ’11’. Числа изменить не могу, ибо по условию задачи так положено. Что здесь можно сделать?

C++
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
26
27
28
29
30
31
32
33
34
35
36
37
...
cout<<"nnZadanie 3nn";
    int m;
    cout<<"Vvedite nomer mesyaza (ot 1 do 12)n";
    cout<<"m= ";
    cin>>m;
    switch(m)
    {
    case '1': cout<<"Zima";
    break;
    case '2': cout<<"Zima";
    break;
    case '3': cout<<"Vesna";
    break;
    case '4': cout<<"Vesna";
    break;
    case '5': cout<<"Vesna";
    break;
    case '6': cout<<"Leto";
    break;
    case '7': cout<<"Leto";
    break;
    case '8': cout<<"Leto";
    break;
    case '9': cout<<"Osen'";
    break;
    case '10': cout<<"Osen'"; // вот здесь ловит ступор //
    break;
    case '11': cout<<"Osen'";
    break;
    case '12': cout<<"Zima";
    break;
        
    default: cout<<"Takogo mesyaza net!";
                
    system("pause");
    }

Это кусок программы.



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

09.03.2016, 23:54

11

hoggy

Эксперт С++

8726 / 4305 / 959

Регистрация: 15.11.2014

Сообщений: 9,752

10.03.2016, 00:05

2

Лучший ответ Сообщение было отмечено Maria Shakun как решение

Решение

Цитата
Сообщение от Maria Shakun
Посмотреть сообщение

он ловит ошибку на case ’11’

у всех циферок убрать апострофы.

пример:
было так:

C++
1
case '1': cout<<"Zima";

стало так:

C++
1
case 1: cout<<"Zima";

было так:

C++
1
case '11': cout<<"Osen";

стало так:

C++
1
case 11: cout<<"Osen";



1



0 / 0 / 0

Регистрация: 09.03.2016

Сообщений: 5

10.03.2016, 00:12

 [ТС]

3

Теперь тормозит на case 12. Там тоже указано Zima, как и в case 1. Это может быть как-то связано?



0



Вездепух

Эксперт CЭксперт С++

10928 / 5920 / 1619

Регистрация: 18.10.2014

Сообщений: 14,880

10.03.2016, 00:15

4

Цитата
Сообщение от Maria Shakun
Посмотреть сообщение

на case ’10’ выдает ошибку

Это какой компилятор так себя ведет?

Ваш код, конечно, не верен с точки зрения функциональности, как уже заметили. Но формально и немедленной ошибки в вашем case ’10’ нет. Предупреждение компилятор на всякий случай может выдать, но вот ошибку-то за что?

Добавлено через 47 секунд

Цитата
Сообщение от Maria Shakun
Посмотреть сообщение

Теперь тормозит на case 12.

Что такое «тормозит»? Потрудитесь выражаться яснее.



1



0 / 0 / 0

Регистрация: 09.03.2016

Сообщений: 5

10.03.2016, 00:20

 [ТС]

5

Внизу компилятор выдает ошибку по поводу строчки с case 12.

Миниатюры

C++, ошибка в операторе switch (case)
 



0



Эксперт С++

8726 / 4305 / 959

Регистрация: 15.11.2014

Сообщений: 9,752

10.03.2016, 00:26

6

Цитата
Сообщение от Maria Shakun
Посмотреть сообщение

Внизу компилятор выдает ошибку по поводу строчки с case 12.

диагноз:
русские буквы в файловых путях к проекту.

лекарство:
переименовать имя каталога «Лабораторные работы с++»
в «trololo».

после чего повторить попытку сборки и запуска.



1



Вездепух

Эксперт CЭксперт С++

10928 / 5920 / 1619

Регистрация: 18.10.2014

Сообщений: 14,880

10.03.2016, 00:28

7

Цитата
Сообщение от Maria Shakun
Посмотреть сообщение

Внизу компилятор выдает ошибку по поводу строчки с case 12.

Не несите ерунды. Никакого отношения к строчке с 12 эта ошибка не имеет.

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



1



20 / 10 / 2

Регистрация: 07.03.2016

Сообщений: 211

10.03.2016, 01:04

8

либо программа заработала, и девушка на радостях позабыла поблагодарить,
либо у неё закончились доводы, что не заработало.
а d:program files(x86)
и D:Лабораторные работы С++ — в этой компиляторе с скриншота —
диски разные, что ли?

~компилятор говорит, что билд запущен, и второй экземпляр билда, для отладки, — запущен быть не может, что ли?
*просто на скрине нету сообщения компилятора. мде. вообще девушка неумеха, не сделала даже скрин.
то есть, для этого 2й компьютер надо?



1



Maria Shakun

0 / 0 / 0

Регистрация: 09.03.2016

Сообщений: 5

10.03.2016, 10:34

 [ТС]

9

Нет, просто не могла ответить вчера. Всё заработало. Достаточно было убрать апострофы. Всем огромное спасибо!

Добавлено через 34 минуты
Мне преподаватель посоветовала код сократить:

C++
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
...
cout<<"nnZadanie 3nn";
    int m;
    cout<<"Vvedite nomer mesyaza (ot 1 do 12)n";
    cout<<"m= ";
    cin>>m;
    switch(m)
    {
    case 1 ... 2: case 12: cout<<"Zima";
    break;
    
    case 3 ... 5: cout<<"Vesna";
    break;
    
    case 6 ... 8: cout<<"Leto";
    break;
    
    case 9 ... 11: cout<<"Osen'";
    break;
    
            
    default: cout<<"Takogo mesyaza net!";
                
    system("pause");
    }

В качестве совета остальным оставлю это здесь. Так экономичнее в плане времени. :-)



0



TheCalligrapher

Вездепух

Эксперт CЭксперт С++

10928 / 5920 / 1619

Регистрация: 18.10.2014

Сообщений: 14,880

10.03.2016, 10:43

10

Цитата
Сообщение от Maria Shakun
Посмотреть сообщение

Мне преподаватель посоветовала код сократить:

C++
1
case 6 ... 8:

Такого синтаксиса ни язык С++, ни язык С не поддерживает. Это не более чем «расширение» языка от конкретного компилятора, к стандартному С++ никакого отношения не имеющее. Так что советы вашего преподавателя — несколько мимо кассы.

Отдельный вопрос: ‘system(«pause»)’ у вас внутрь ‘switch’ попало намеренно или случайно?



0



70 / 70 / 52

Регистрация: 24.01.2013

Сообщений: 198

10.03.2016, 16:14

11

Отдельный вопрос: ‘system(«pause»)’ у вас внутрь ‘switch’ попало намеренно или случайно?

отсутствует закрывающая скобка } после default )



0



0 / 0 / 0

Регистрация: 09.03.2016

Сообщений: 5

11.03.2016, 22:26

 [ТС]

12

Случайно. Хотя и так оно работает так, как требуют на занятии…



0



Я уверен, что вы уже знакомы с основами SQL CASE, поэтому я не буду мучит вас длинным введением. Давайте углубимся в понимание того, что происходит под капотом.

1. SQL CASE не всегда оценивается последовательно

Выражения в SQL CASE по большей части оцениваются последовательно или слева направо. Хотя совсем другое дело, когда они используются с агрегатными функциями. Давайте рассмотрим пример:

-- сначала оценивается агрегатная функция и генерирует ошибку
DECLARE @value INT = 0;
SELECT CASE WHEN @value = 0 THEN 1 ELSE MAX(1/@value) END;

Вышеприведенный код выглядит обычно. Если я спрошу вас, какой результат будет получен, вы, вероятно, ответите 1. Визуальная проверка скажет нам это, поскольку переменная @value установлена в 0. Если @value равна 0, то результат равен 1.

Но не в этом случае. Вот действительный результат, полученный в SQL Server Management Studio:

Msg 8134, Level 16, State 1, Line 4
Divide by zero error encountered.

Но почему?

Когда условное выражение использует агрегатные функции типа MAX() в SQL CASE, они оцениваются в первую очередь. Таким образом, MAX(1/@value) вызывает ошибку деления на нуль, поскольку @value равна 0.

Ситуация становится еще более неприятной, когда скрыта. Я объясню это позже.

2. Простое выражение SQL CASE оценивается многократно

Ну и что?

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

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

Теперь рассмотрим следующий очень простой пример:

SELECT TOP 1 manufacturerID FROM SportsCars

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


Рис.1. Логические чтения таблицы SportsCars до использования запроса в качестве подзапроса в SQL CASE

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

План выполнения тоже показывает простой процесс:


Рис.2. План выполнения для запроса к SportsCar до его использования как подзапроса в SQL CASE

Давайте теперь поместим этот запрос в выражение CASE:

-- Использование подзапроса в SQL CASE
DECLARE @manufacturer NVARCHAR(50)
SET @manufacturer = (CASE (SELECT TOP 1 manufacturerID FROM SportsCars)
WHEN 6 THEN 'Alfa Romeo'
WHEN 21 THEN 'Aston Martin'
WHEN 64 THEN 'Ferrari'
WHEN 108 THEN 'McLaren'
ELSE 'Others'
END)
SELECT @manufacturer;

Анализ

Скрестите пальцы, поскольку сейчас логические чтения увеличатся в 4 раза.


Рис.3. Логические чтения после использования подзапроса в SQL CASE

Удивительно! По сравнению всего с двумя логическими чтениями на рис.1 мы получили в 4 раза больше. Таким образом, запрос стал в 4 раза медленнее. Как это могло произойти? Мы видим подзапрос только в одном месте.

Но это не конец истории. Посмотрите план выполнения:


Рис.4. План выполнения после использования простого запроса в качестве выражения подзапроса в SQL CASE

Мы видим 4 экземпляра операторов Top и Index Scan на рис.4. Если каждый Top и Index Scan потребляет 2 логических чтения, это объясняет, почему число логических чтений стало 8 на рис.3. И, поскольку каждый Top и Index Scan имеют 25% стоимости, это подтверждает сказанное.

Но это еще не все. Свойства оператора Compute Scalar показывают, как обрабатывается весь оператор.


Рис.5. Свойства Compute Scalar показывают 4 выражения CASE WHEN

Мы видим 3 выражения CASE WHEN в свойстве Defined Values оператора Compute Scalar. Это выглядит так, как будто простое выражение CASE стало поисковым выражением CASE типа:

DECLARE @manufacturer NVARCHAR(50)
SET @manufacturer = (CASE
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 6 THEN 'Alfa Romeo'
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 21 THEN 'Aston Martin'
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 64 THEN 'Ferrari'
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 108 THEN 'McLaren'
ELSE 'Others'
END)
SELECT @manufacturer;

Хорошее исправление? Давайте посмотрим логические чтения в STATISTICS IO:


Рис.6. Логические чтения после извлечения подзапроса из выражения CASE

Мы видим меньше логических чтений в модифицированном запросе. Извлечение подзапроса и присвоение результата переменной получается значительно лучше. Что насчет плана выполнения? Посмотрите ниже:


Рис.7. План выполнения после извлечения подзапроса из выражения CASE

Оператор Top и Index Scan появляются однажды, а не 4 раза. Замечательно!

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

Эти три встроенные функции тайно преобразуются в SQL CASE

Есть секрет, и SQL CASE имеет к нему отношение. Если вы не знаете, как ведут себя эти 3 функции, вы не будете знать, что совершаете ошибку, которую мы пытались избежать в пунктах №1 и №2 выше. Вот они:

  • IIF
  • COALESCE
  • CHOOSE

Давайте рассмотрим их по очереди.

IIF

Я использовал Immediate IF, или IIF, в Visual Basic и Visual Basic for Applications. Это является также эквивалентом тернарного оператор в C#: <условие> ? <результат, если истинно> : <результат, если ложно>.

Эта функция принимает условие и возвращает 1 из 2 аргументов в зависимости от результатов условия. И эта функция также имеется в T-SQL.

Но это просто обертка более длинного выражения CASE. Откуда нам это известно? Давайте проверим пример.

SELECT IIF((SELECT Model FROM SportsCars WHERE SportsCarID = 1276) = 
'McLaren Senna', 'Yes', 'No');

Результатом этого запроса является ‘No’. Однако проверьте план выполнения, а также свойства Compute Scalar.


Рис.8. IIF оказывается CASE WHEN в плане выполнения

Поскольку IIF является CASE WHEN, как вы думаете, что произойдет, если выполнить что-то подобное этому?

DECLARE @averageCost MONEY = 1000000.00;
DECLARE @noOfPayments TINYINT = 0; -- умышленно вызвать ошибку
SELECT IIF((SELECT Model FROM SportsCars WHERE SportsCarID = 1276) = 'SF90 Spider', 83333.33,MIN(@averageCost / @noOfPayments));

Будет получена ошибка деления на нуль, если @noOfPayments равен нулю. То же самое происходило в первом случае, рассмотренном ранее.

Вы можете спросить, что вызывает эту ошибку, поскольку результатом запроса является TRUE, и должно получиться 83333.33. Опять вернитесь к случаю 1.

Таким образом, если вы столкнулись с такой ошибкой при использовании IIF, виноват SQL CASE.

COALESCE

COALESCE — это также сокращенная форма выражения SQL CASE. Она оценивает список значений и возвращает первое не-NULL значение. Вот пример, который показывает, что подзапрос вычисляется дважды.

SELECT 
COALESCE(m.Manufacturer + ' ','') + sc.Model AS Car
FROM SportsCars sc
LEFT JOIN Manufacturers m ON sc.ManufacturerID = m.ManufacturerID

Давайте посмотрим план выполнения и свойство Defined Values оператора Compute Scalar.


Рис.9. COALESCE преобразуется в SQL CASE в плане выполнения

Разумеется SQL CASE. Нигде не упоминается COALESCE в окне Defined Values. Это доказывает тайный секрет этой функции.

Но это не все. Сколько раз вы увидели [Vehicles].[dbo].[Styles].[Style] в окне Defined Values? ДВАЖДЫ! Это согласуется с официальной документацией Microsoft. Представьте, что один из аргументов в COALESCE является подзапросом. Тогда получаем удвоение логических чтений и замедление выполнения.

CHOOSE

Наконец, CHOOSE. Она подобна функции CHOOSE в MS Access. Она возвращает одно значение из списка значений на основе позиции индекса. Она также действует как индекс массива.

Давайте посмотрим, сможем ли мы получить трансформацию в SQL CASE в примере. Проверьте нижеприведенный код:

;WITH McLarenCars AS 
(
SELECT
CASE
WHEN sc.Model IN ('Artura','Speedtail','P1/ P1 GTR','P1 LM') THEN '1'
ELSE '2'
END AS [type]
,sc.Model
,s.Style
FROM SportsCars sc
INNER JOIN Styles s ON sc.StyleID = s.StyleID
WHERE sc.ManufacturerID = 108
)
SELECT
Model
,Style
,CHOOSE([Type],'Hybrid','Gasoline') AS [type]
FROM McLarenCars

Это наш пример с CHOOSE. Теперь давайте посмотрим план выполнения и свойство Defined Values в операторе Compute Scalar:


Рис.10. Как видно в плане выполнения CHOOSE преобразуется в SQL CASE

Вы видите ключевое слово CHOOSE в окне Defined Values на рис.10? Как насчет CASE WHEN?

Подобно предыдущим примерам, эта функция CHOOSE есть просто оболочка для более длинного выражения CASE. И поскольку запрос имеет 2 пункта для CHOOSE, ключевые слова CASE WHEN появляются дважды. Смотрите в окне Defined Values красные прямоугольники.

Однако CASE WHEN появлялось более двух раз. Это происходит из-за выражения CASE во внутреннем запросе CTE. Если посмотреть внимательно, эта часть внутреннего запроса также появляется дважды.

На заметку

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

  1. SQL CASE ведет себя иначе, когда используются агрегатные функции. Будьте внимательны при передаче аргументов в агрегатные функции типа MIN, MAX или COUNT.
  2. Простое выражение CASE будет оцениваться несколько раз. Имейте это в виду и избегайте передачи подзапроса. Хотя это синтаксически корректно, это повредит производительности.
  3. IIF, CHOOSE и COALESCE имеют грязные секреты. Помните это, передавая значения в эти функции. Это вызовет преобразование к SQL CASE. В зависимости от значений вы можете получить ошибку или ухудшить производительность.

Надеюсь, что различие в поведении SQL CASE было полезным для вас.

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

Что такое условная логика?

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

Например, в базе данных «Расписание» есть таблица Student с полем birthday, отражающим дату рождения студента. Допустим,
в выборке необходимо отобразить не саму дату рождения, а текстовое значение «Совершеннолетний» или «Несовершеннолетний» в зависимости от того,
есть ли студенту 18 лет. Это и есть пример условной логики, при которой должно вывестись либо одно значение, либо другое
в зависимости от конкретного условия.

Реализация такого запроса с помощью CASE может выглядеть следующим образом:

SELECT first_name, last_name,
CASE
  WHEN TIMESTAMPDIFF(YEAR, birthday, NOW()) >= 18 THEN "Совершеннолетний"
  ELSE "Несовершеннолетний"
END AS status
FROM Student

Синтаксис поискового выражения CASE

CASE
    WHEN условие_1 THEN возвращаемое_значение_1
    WHEN условие_2 THEN возвращаемое_значение_2
    WHEN условие_n THEN возвращаемое_значение_n
    [ELSE возвращаемое_значение_по_умолчанию]
END

Если условие_1 возвращает истинное значение, то выражение CASE вернёт возвращаемое_значение_1, иначе будет сделана проверка
на условие_2 и т.д. Если ни одно из предложенный условий не будет выполнено, то вернётся NULL или возвращаемое_значение_по_умолчанию,
если была использована конструкция ELSE.

Пример

Рассмотрим оператор CASE на примере определения этапа школьного образования.

Этапы школьного образования

SELECT name,
CASE
  WHEN SUBSTRING(name, 1, INSTR(name, ' ')) IN (10, 11) THEN "Старшая школа"
  WHEN SUBSTRING(name, 1, INSTR(name, ' ')) IN (5, 6, 7, 8, 9) THEN "Средняя школа"
  ELSE "Начальная школа"
END AS stage
FROM Class
  • Сначала мы извлекаем номер класса из его названия
    SUBSTRING(name, 1, INSTR(name, ' '))
    
  • Далее мы проверяем вхождение данного номера в список классов, относящихся к «Старшая школа» и «Средняя школа».
  • Если номер класса не находится в диапазоне 5–11, мы выводим «Начальная школа».

Синтаксис простого выражения CASE

Оператор CASE также имеет и более простой синтаксис, который схож с поисковым выражением CASE, но
является менее гибким. Так он выглядит в общем виде:

CASE значение
    WHEN сравниваемое_значение_1 THEN возвращаемое_значение_1
    WHEN сравниваемое_значение_2 THEN возвращаемое_значение_2
    WHEN сравниваемое_значение_n THEN возвращаемое_значение_n
    [ELSE возвращаемое_значение_по-умолчанию]
END

В этом синтаксисе значение в CASE поочерёдно сравнивается с переданными значениями в WHEN и при совпадении возвращается значение следующее за THEN.

Используя этот синтаксис, можно переписать наш предыдущий пример таким образом:

SELECT name,
CASE SUBSTRING(name, 1, INSTR(name, ' '))
  WHEN 11 THEN "Старшая школа"
  WHEN 10 THEN "Старшая школа"
  WHEN 9 THEN "Средняя школа"
  WHEN 8 THEN "Средняя школа"
  WHEN 7 THEN "Средняя школа"
  WHEN 6 THEN "Средняя школа"
  WHEN 5 THEN "Средняя школа"
  ELSE "Начальная школа"
END AS stage
FROM Class

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

Какое значение вернёт оператор CASE в данном случае?

CASE 2
  WHEN 0 THEN "Ноль"
  WHEN 1 THEN "Один"
  ELSE "Много"
END

«Программы без ошибок можно написать
двумя способами, но работает — третий»
Алан Джей Перлис

Приветствую вас на нашем очередном занятии. Сегодня урок будет посвящен оператору варианта Case.
Оператор Case — это оператор множественного ветвления. То есть в зависимости от некоторого условия может быть выполнено одно из многочисленных продолжений программы. Рассмотрим структуру оператора Case, а затем я поясню на бытовом примере, как это работает.

Case <селектор> of
    <константа 1> : <оператор 1>;
    <константа 2> : <оператор 2>;
    .............................
    <константа N> : <оператор N>;
    else <оператор>
end;

где Case — зарезервированное слово (от англ. «выбор», «вариант»);
<селектор> — выражение, исходя из значения которого будет выбран оператор из списка для дальнейшего выполнения;
of — зарезервированное слово (от англ. «из»);
<константа> — константа выбора;
<оператор> — любые операторы языка Pascal, в том числе может быть составной или пустой операторы;
else — зарезервированное слово (от англ. «иначе»). Если ни одна из констант не подошла к селектору, то будут выполнены операторы, следующие за else. Блок else не обязателен, поэтому если его нет, оператор case завершит свою работу, так и не выполнив ни одного оператора из списка;
end — зарезервированное слово (от англ. «конец»), завершение оператора варианта.

Разберем работу оператора Case на примере. Каждый из вас, прежде чем выйти на улицу одевает одежду. Выбор этой одежды во многом зависит от температуры на улице. Если на термометре -15, то вы наденете куртку, брюки и сапоги. А если на улице +20, ваш выбор будет состоять из майки, шорт и сандалий. Представьте, что термометр с его показаниями температуры — это своего рода <селектор> в программе. В роли <констант> выступают градусы цельсия, а в роли <операторов> ваш гардероб. Тогда программу, которая выбирает гардероб в зависимости от температуры, можно записать следующим образом:

program garderob;
var
   temperatura:integer;
begin
     write('Температура = ');
     read(temperatura);
     case temperatura of
      -24..-15 : writeln('Шапка-ушанка, фуфайка, ватные штаны, валенки');
      -14..0 : writeln('Шапка, теплая куртка, штаны, ботинки');
      1..10 :  writeln('Куртка, штаны, ботинки');
      11..17 : writeln('Ветровка, джинсы, кроссовки');
      18..25 : writeln('Кепка, майка, сандалии');
      26..35 : writeln('Плавки, маска, ласты');
      else writeln('Лучше остаться дома')
     end;
end.

Пользователь вводит значение температуры, если это значение расположено в интервале от -24 до +35 градусов цельсия, то программа находит среди констант ту, которая равна введенному значению, и выводит на экран список гардероба, соответствующий этой температуре. Если введенное значение температуры лежит за пределом от -24 до +35, то на экран выводится сообщение из блока else — ‘Лучше остаться дома’.

Несколько важных замечаний

  • Тип селектора должен быть ординальным. То есть он может быть любого типа, кроме вещественного Real (более подробно о типах данных читай здесь);
  • Тип константы должен совпадать с типом селектора. То есть, если у вас селектор имеет тип integer, то и константы выбора должны быть типа integer;
  • Каждое из постоянных значений должно быть сопоставлено самое большее с одним оператором. То есть, говоря простым языком, константы не должны повторяться;
  • Константы выбора НЕ являются метками. То есть на них нельзя ссылаться в операторе перехода goto (об этом операторе будет отдельный урок).

Примеры ошибочного написания оператора Case:

Пример №1 — селектор не может иметь тип real

program one;
var
   x:real;
begin
     read(x);
     case x of
     1 : writeln('one');
     2 : writeln('two');
     3 : writeln('three');
     4 : writeln('four');
     end;
end.

Пример №2 — тип констант не совпадает с типом селектора:

program two;
var
   x:integer;
begin
     read(x);
     case x of
     'A' : writeln('one');
     'B' : writeln('two');
     'C' : writeln('three');
     'D' : writeln('four');
     end;
end.

Пример №3 — повторение константы (константа 2 встречается два раза в списке):

program three;
var
   x:integer;
begin
     read(x);
     case x of
     1,2 : writeln('one');
     2,3 : writeln('two');
     4 : writeln('three');
     5..7 : writeln('four');
     end;
end.

Кстати, в этом примере наглядно показано, что <константа> может быть не только простым числом, но и представлять собой некий диапазон. Запись диапазона происходит следующим образом: <начало>..<конец> Также <константа> может быть задана перечисляемым списком. Такой список записывается через запятую, например (при x:integer):

case x of
  0, 1, 2 : <операторы 1>;
  3, 4, 5 : <операторы 2>;
  6, 9, 15 : <операторы 3>;
end;

через запятую и в одинарных кавычках (при x:char):

case x of
  'A', 'B', 'C' : <операторы 1>;
  'D', 'E', 'F' : <операторы 2>;
  'Monday', 'Tuesday', 'Wednesday' : <операторы 3>;
end;

Это все, о чем я хотел вам сегодня рассказать. Надеюсь, материал был понятен. Для закрепления навыков обязательно посетите раздел Практика, в нем собраны задачи по разным темам и даны готовые решения. Если возникли какие-то вопросы, не стесняйтесь задавать их, контакты для связи со мной находятся здесь. Если вопросов нет — жду вас на следующем уроке. Всего доброго!

Понравилась статья? Поделить с друзьями:
  • Cas computing scale весы ошибка
  • Cas ci 5010a ch02 ошибка
  • Carrier как сбросить ошибка al22
  • Carrier viento 200 ошибка e2p
  • Carrier viento 200 коды ошибок