ТОП 10:

Множественный выбор. Оператор переключения



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

Для осуществления подобных операций в языке Си существует специальный оператор "switch" -переключатель. Используя этот оператор, вместо вложенных "if" в предыдущей программе можно записать следующую конструкцию:

 

switch ( choice )

{

case 1 : fun=sin(x); break;

case 2 : fun=cos(x); break;

case 3 : fun=tan(x); break;

case 4 : loop=0; break;

default: printf( "Неверный выбор\n" ); break;

}

 

Здесь ключевое слово "case" (случай) указывает на то, что следующая константа является значением переменной choice, для которого выполняются соответствующие действия.

Оператор "break;" осуществляет выход из оператора "switch", а не из цикла. Именно поэтому для выхода из цикла пришлось использовать специальный флаг loop.

Ключевое слово "default" ( умолчание ) означает, что следом записаны действия, выполняющиеся, если значение choice не совпадет ни с одной из констант, указанных за "case".

Оператор switch в общем виде выглядит так:

 

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

 

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

"{"

"case" константа ":" { оператор }

"case" константа ":" { оператор }

[ "default" ":" { оператор } ]

"}"

 

В качестве выражения можно использовать любое выражение, имеющее символьный или целый тип. Константы тоже должны быть символьного или целого типа, например case 4 , case 'A'.

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

 

case 2 :

case 4 :

case 8 : f = sin(x); break;

 

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

 

switch( ch )

{

case 'A' :

case 'B' : x++;

case 'C' :

case 'D' : f = sin(x); break;

case 'E' : f = cos(x); break;

}

 

будет вычислено f=sin(x+1), при ch равном 'A' или 'B'; f=sin(x), при ch равном 'C' или 'D'; f=cos(x), при ch равном 'E'.

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

Оператор цикла do-while.

Оператор цикла do-while предназначен для реализации циклических алгоритмов и имеет следующую форму записи

 

 

цикл_do-while =

"do" оператор "while" "("выражение")" ";"

 

Оператор выполняется циклически до тех пор, пока выражение отлично от нуля. В отличие от оператора while, тело оператора do-while выполняется хотя бы один раз до первого вычисления условия.

Работу оператора do-while проиллюстрируем на примере программы, которая определяет корень уравнения x-cos(sin(x))=0 методом итераций, который заключается в циклическом вычислении очередного приближения x_new по предыдущему приближению x_old, согласно выражению x_new=cos(sin(x_old)), вытекающему из исходного уравнения. Процесс итерации заканчивается тогда, когда x_new станет равен x_old. Программа, реализующая этот алгоритм, приведена ниже.

 

#include <stdio.h>

#include <math.h>

 

/* Решение уравнения x-cos(sin(x))=0 */

void main (void)

{

double x_new=0.9, x_old, eps=0.0001;

do

{

x_old = x_new;

x_new = cos(sin(x_old));

} while ( fabs( x_new - x_old ) > eps );

printf ( "x=%lf", x_new );

}

 

Сравнение двух вещественных чисел осуществляется с использованием точности eps. Это необходимо потому, что из-за погрешностей округления прямая проверка на равенство двух вещественных чисел скорее всего даст в результате 0 (ложь).

Перечисления. Работа с клавиатурой IBM PC

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

 

перечисление =

"enum" [ имя_перечисления ]

"{"

имя_конст [ "=" конст_выр ]

{ "," имя_конст [ "=" конст_выр ] }

"};"

 

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

Если константное выражение отсутствует, то имени назначается значение предыдущего выражения, увеличенное на единицу. Если отсутствует выражение, соответствующее первому имени константы, то ему назначается значение 0. Например:

 

enum DAYS { MON=1, TUE, WED, THU, FRI, SAT, SUN };

enum MONTH { JAN=1, FEB, MAR, APR, MAY, JUN,

JUL, AUG, SEP, OCT, NOV, DEC };

 

В дальнейшем в программе эти имена можно использовать вместо целых констант. Например, DEC вместо 12, THU вместо 4 и т. д.

Рассмотрим использование перечислений для организации удобной работы с клавиатурой IBM PC.

В библиотеке conio имеется функция, осуществляющая ввод одиночного символа (точнее его кода) без отображения его на экране дисплея. Она имеет следующий прототип:

 

int getch( void );

 

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

Некоторым клавишам клавиатуры не соответствует ни один символ из кодовой таблицы. При нажатии на подобные клавиши getch() вначале возвращает нулевое значение. Если при этом обратиться к функции повторно, то она возвратит условный номер клавиши на клавиатуре, так называемый скэн-код. Это свойство используется в функции GetCh() для расширения возможностей getch(). Функция GetCh() будет возвращать коды символов в обычных случаях. При нажатии специальной клавиши GetCh() возвратит скэн-код, увеличенный на 256 (0x100) или на 512 (0x200), в зависимости от того, была ли нажата клавиша Shift или нет. Текст функции GetCh() приводится ниже.

 

#include <conio.h>

#include <bios.h>

/* Ввод одиночного символа с клавиатуры */

int GetCh( void )

{

int ch;

if( ( ch = getch() ) == 0 )

ch = getch() | ( bioskey(2) & 3 ? 0x200 : 0x100 );

return ch;

}

 

Здесь, выражение bioskey(2) & 3 осуществляет проверку нажатия клавиши Shift и отлично от нуля, если последняя нажата.

Прототип функции GetCh() и коды специальных клавиш перечисления KeyboardCodes, получаемых с помощью этой функции, следует поместить в файл, например, keyboard.h и в дальнейшей использовать не числовые значения кодов, а только символические имена. Фрагмент перечисления KeyboardCodes приведен ниже:

 

enum KeyboardCodes

{

kbF1 = 315, kbF2, kbF3, kbF4, ..., kbF10,

kbShiftF1 = 596, kbShiftF2, kbShiftF3, ..., kbShiftF10,

kbCtrlF1 = 350, kbCtrlF2, kbCtrlF3, ..., kbCtrlF10,

kbAltF1 = 360, kbAltF2, kbAltF3, ..., kbAltF10,

kbAlt1 = 376, kbAlt2, kbAlt3, ..., kbAlt0,

kbAltQ = 272, kbAltW, kbAltE, ..., kbAltP,

kbAltA = 286, kbAltS, kbAltD, ..., kbAltL,

kbAltZ = 300, kbAltX, kbAltC, ..., kbAltM,

kbCtrlA = 1, kbCtrlB, kbCtrlC, ..., kbCtrlZ,

 

kbUp = 328, kbDown = 336, kbTab = 9,

kbCtrlUp = 397, kbCtrlDown = 401, kbCtrlTab = 404,

kbAltUp = 408, kbAltDown = 416, kbAltTab = 421,

kbShiftUp = 584, kbShiftDown = 592, kbShiftTab = 527,

 

kbRight = 333, kbLeft = 331, kbEsc = 27,

kbCtrlRight = 372, kbCtrlLeft = 371,

kbAltRight = 413, kbAltLeft = 411, kbAltEsc = 257,

kbShiftRight = 589, kbShiftLeft = 587,

 

kbPgUp = 329, kbPgDn = 337, kbIns = 338,

kbCtrlPgUp = 388, kbCtrlPgDn = 374, kbCtrlIns = 513,

kbAltPgUp = 409, kbAltPgDn = 417, kbAltIns = 418,

kbShiftPgUp = 585, kbShiftPgDn = 593, kbShiftIns = 594,

 

kbHome = 327, kbEnd = 335, kbDel = 339,

kbCtrlHome = 375, kbCtrlEnd = 373, kbCtrlDel = 515,

kbAltHome = 407, kbAltEnd = 415, kbAltDel = 419,

kbShiftHome = 583, kbShiftEnd = 591, kbShiftDel = 595,

 

kbEnter = 13, kbBackspace = 8,

kbCtrlEnter = 10, kbCtrlBackspace = 127,

kbAltEnter = 284, kbAltBackspace = 270

};

 

Предложенная методика работы с клавиатурой IBM PC не требует никаких изменений исходных текстов программ, использующих функцию GetCh(), в случае изменения аппаратных средств.

Пример организации светового меню

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

Экран IBM PC имеет 25 строк и 80 позиций. Нумерация строк и позиций начинается с 1. Первая строка находится вверху, первая позиция слева. Все необходимые функции работы с экраном IBM PC имеются в библиотеке компилятора, их прототипы находятся в файле conio.h. Рассмотрим некоторые из этих функций:

 

void clrscr( void ); - осуществляет стирание экрана;

void gotoxy( int x, int y ); - перемещает курсор в позицию x строки y;

void cprintf( char *format, ... ); - выполняет то же самое, что и printf, но выводит информацию, используя установленный цвет фона и цвет символа;

void textcolor( int color ); - установка цвета символа с кодом color;

void textbackground( int color ); - установка цвета фона с кодом color;

 

Последние функции не изменяют цвет уже выведенных символов. Их влияние распространяется на все последующие выводы с помощью функции cprintf.

При установке цвета допускается использовать шестнадцать цветов символа с кодами 0...15, и восемь цветов фона с кодами 0...7. Для удобства работы с цветами в conio.h определены мнемонические имена для цветов:

 

enum COLORS {

/* цвета для символов и фона */

BLACK /* черный */, BLUE /* синий */,

GREEN /* зеленый */, CYAN /* салатовый */,

RED /* красный */, MAGENTA /* малиновый */,

BROWN /* коричневый */, LIGHTGRAY /* светло-серый */,

/* цвета только для символов */

DARKGRAY /*темно-серый */, LIGHTBLUE /* ярко-синий */,

LIGHTGREEN /*ярко-зеленый*/, LIGHTCYAN /*ярко-салатовый*/,

LIGHTRED /*ярко-красный*/, LIGHTMAGENTA /*ярко-малиновый*/,

YELLOW /* желтый */, WHITE /* белый */ };

Приведенная ниже программа вычисляет функции sin(x), cos(x) и tan(x) в зависимости от выбора пользователя. Выбор осуществляется с помощью светового меню. Движение светового окна организуется путем перерисовки пункта меню другим цветом фона. Основной цикл этой программы управляет изменением переменной choice, в которой хранится текущий выбор пользователя.

 

#include <stdio.h>

#include <math.h>

#include <conio.h>

#include "keyboard.h"

 

#define N 4

#define ROW 10

#define COL 35

#define TEXT_C WHITE

#define TEXT_BG BLACK

#define CHOICE_BG LIGHTGRAY

 

void out_str( int num, int bg_color );

 

/* Организация светового меню */

void main ( void )

{

int loop; /* Флаг конца работы */

int choice; /* Текущий выбор пункта меню */

int old_choice; /* Старый выбор пункта меню */

double fun, x; /* Значения функции и аргумента */

int i;

textbackground( TEXT_BG ); textcolor( TEXT_C );

clrscr(); gotoxy( COL, ROW-1 );

cprintf( "Аргумент x=" ); scanf( "%lf", &x );

/* Начальный вывод всех пунктов меню */

i=1; while( i <= N ) { out_str( i, TEXT_BG ); i++; }

loop = 1; choice = 1; old_choice = 2;

while ( loop )

{

out_str( old_choice, TEXT_BG );

out_str( choice, CHOICE_BG );

old_choice = choice;

switch( GetCh() )

{

case kbUp :

if ( choice>1 ) choice--; else choice = N; break;

case kbDown :

if ( choice<N ) choice++; else choice = 1; break;

case kbEnter :

switch ( choice )

{

case 1 : fun=sin(x); break;

case 2 : fun=cos(x); break;

case 3 : fun=tan(x); break;

case 4 : loop=0; continue;

}

textbackground( TEXT_BG ); gotoxy( COL-5, ROW+6 );

cprintf( "Значение функции %lf\n", fun );

}

}

}


 

/* Функция вывода строки меню с указанным цветом фона */

void out_str( int num, int bg_color )

{

textbackground( bg_color ); gotoxy( COL, ROW+num );

switch( num )

{

case 1: cprintf( "1. sin(x) " ); break;

case 2: cprintf( "2. cos(x) " ); break;

case 3: cprintf( "3. tan(x) " ); break;

case 4: cprintf( "4. Конец работы" ); break;

}

}

 

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







Последнее изменение этой страницы: 2016-04-08; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.219.167.194 (0.016 с.)