C++ Программирование в среде С++ Builder 5

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


Часто возникают ситуации, когда некоторая переменная может принимать несколько возможных значений-вариантов, и для каждого варианта требуется выполнить какие-то свои действия. Например, пользователю может быть предложено меню, когда нажатие различных клавиш инициирует соответствующие команды. Управляющая конструкция, реализующая такую логику, может использовать “последовательно вложенные” операторы if...else if...:

int key;

printf("\nSelect command (F, M or Q): ");

// Вывести подсказку. key = getch();

// Прочитать символ. key = toupper(key);

// Преобразовать в верхний регистр. if (key == 'F')

// Определение команды...

printf("\n\"F\" selected - means File.\n");

else if (key == 'M')

printf("\n\"M\" selected - means Message.\n");

else if (key == 'Q')

printf("\n\"Q\" selected - means Quit.\n");

else



printf("\nlnvalid key!");

Здесь мы применили функцию преобразования символа в верхний регистр toupper (), чтобы можно было вводить букву команды в обоих регистрах (например, F или f).

Условия операторов if содержат проверку кода нажатой клавиши на равенство одному из допустимых символов. Если код клавиши не соответствует никакой команде, выводится сообщение об ошибке.

Для подобных случаев в С существует специальная конструкция выбора switch. Выглядит она так:

switch (выражение)

{

case константное_выражение: группа_операторов case константное_выражение: группа_операторов

[default: группа операторов] }

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

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


И еще одна особенность, о которой следует помнить при написании структур switch. Если найдена метка case, совпадающая со значением проверяемого выражения, то выполняется группа_операторов данного case. Однако дело на этом не заканчивается, поскольку, если не принять никаких дополнительных мер, управление “провалится” ниже, на следующую по порядку метку case и т. д., и в результате будут выполнены все операторы до самого конца блока switch. Если это нежелательно (как чаще всего и бывает), в конце группы_операторов case нужно поставить оператор break. Он прерывает выполнение блока switch и передает управление оператору, непосредственно следующему за блоком.

Для иллюстрации мы перепишем предыдущий пример “меню”, оформив его в виде законченной программы, и продемонстрируем попутно еще один управляющий оператор С.



Листинг 3.3. Демонстрация структуры switch





/*

** Switch.с: Оператор выбора.

*/

#pragma hdrstop

#include <stdio.h>

#include <conio.h>

#pragma argsused

int rriain(int argc, char* argv[])

{

int key;

loop:

printf("\nEnter command (F, M or Q): ");

key = getche(); // Прочитать клавишу.

switch (key) ( // Определение команды... case 'f':

case 'F":

printf("\n\"File\" command selected.\n");

break;

case 'm':

case 'M':

printf ("\n\"Mess.age\" command selected.\n");

break;

case 'q':

case 'Q':

printf("\n\"Quit\" command selected.\n");

printf("\nPress a key to Exit...");

getch() ;

return 0; // Возврат в Windows. default:

printf("\nlnvalid command!\n") ;

}

goto loop; // Следующая команда.

}



Рис. 3.3 Программа Switch

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



Чтение команды производится функцией getche(). Она, как и getch (), возвращает код нажатой клавиши, однако в отличие от getch () отображает введенный символ на экране.

Для реализации цикла мы использовали архаический оператор goto, исполнение которого приводит к передаче управления на метку, указанную в операторе. В примере метка с именем loop стоит в самом начале программы. Таким образом, дойдя до конца функции main (), управление возвращается к ее началу и все повторяется снова.



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


Содержание раздела