Литмир - Электронная Библиотека
Содержание  
A
A

<i>}</i>

Сохраните эту программу как menu5.с.

Как это работает

Переписанная функция

getchoice
выводит то же меню, что и в предыдущих примерах, но подпрограммы вывода изменены так, чтобы можно было воспользоваться характеристиками из базы данных
terminfo
. Если вы хотите видеть на экране сообщение "You have chosen:" дольше, чем одно мгновение перед очисткой экрана и подготовкой его к следующему выбору пункта меню, добавьте в функцию
main
вызов
sleep
:

do {

 choice = getchoice(&quot;Please select an action&quot;, menu, input, output);

 printf(&quot;\nYou have chosen: %c\n&quot;, choice);

<i> sleep(1);</i>

} while (choice != 'q');

Последняя функция в этой программе

char_to_terminal
включает в себя вызов функции
putc
, которую мы упоминали в главе 3.

В завершение этой главы бегло рассмотрим пример определения нажатий клавиш.

Обнаружение нажатий клавиш

Пользователи, программировавшие в ОС MS-DOS, часто ищут в ОС Linux эквивалент функции

kbhit
, которая определяет, была ли нажата клавиша, без реального ее считывания. К сожалению, их поиски оказываются безуспешными, поскольку прямого аналога нет. Программисты в среде UNIX не ощущают этого отсутствия, т.к. UNIX запрограммирована так, что программы очень редко (если когда-либо вообще) озабочены ожиданием события. Поскольку это обычный способ применения
kbhit
, ее нехватка редко ощущается в системах UNIX и Linux.

Однако, когда вы переносите программы из MS-DOS, часто удобно эмулировать функцию

kbhit
, которую можно применять на деле в неканоническом режиме ввода (упражнение 5.7).

Упражнение 5.7. Исключительно ваша собственная
kbhit

1. Начните со стандартной заголовочной информации и пары структур для установки параметров терминала.

peek_character
применяется для проверки нажатия клавиши. Далее описываются функции, которые будут использоваться позже:

#include &lt;stdio.h&gt;

#include &lt;stdlib.h&gt;

#include &lt;termios.h&gt;

#include &lt;term.h&gt;

#include &lt;curses.h&gt;

#include &lt;unistd.h&gt;

static struct termios initial_settings, new_settings;

static int peek_character = -1;

void init_keyboard();

void close_keyboard();

int kbhit();

int readch();

2. Функция main вызывает функцию

init_keyboard
для настройки терминала, затем выполняет цикл один раз в секунду, каждый раз вызывая в нем функцию
kbhit
. Если нажата клавиша <q>, функция
close_keyboard
восстанавливает нормальный режим и программа завершается:

int main() {

 int ch = 0;

 init_keyboard();

 while (ch != 'q') {

  printf(&quot;looping\n&quot;);

  sleep(1);

  if (kbhit()) {

   ch = readch();

   printf(&quot;you hit %c\n&quot;, ch);

  }

 }

 close_keyboard();

 exit(0);

}

3. Функции

init_keyboard
и
close_keyboard
настраивают терминал в начале и конце программы:

void init_keyboard() {

 tcgetattr(0, &amp;initial_settings);

 new_settings = initial_settings;

 new_settings.c_lflag &amp;= ~ICANON;

 new_settings.c_lflag &amp;= ~ECHO;

 new_settings.c_lflag &amp;= ~ISIG;

 new_settings.c_cc[VMIN] = 1;

 new_settings.c_cc[VTIME] = 0;

 tcsetattr(0, TCSANOW, &amp;new_settings);

}

void close_keyboard() {

 tcsetattr(0, TCSANOW, &amp;initial_settings);

}

4. Теперь функция, проверяющая нажатие клавиши:

int kbhit() {

 char ch;

 int nread;

 if (peek_character != -1) return 1;

 new_settings.c_cc[VMIN] = 0;

 tcsetattr(0, TCSANOW, &amp;new_settings);

 nread = read(0, sch, 1);

 newrsettings.c_cc[VMIN] = 1;

 tcsetattr(0, TCSANOW, &amp;new_settings);

 if (nread == 1) {

  peek_character = ch;

  return 1;

 }

 return 0;

}

5. Нажатый символ считывается следующей функцией

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

int readch() {

 char ch;

 if (peek_character != -1) {

  ch = peek_character;

  peek_character = -1;

  return ch;

 }

 read(0, &amp;ch, 1);

93
{"b":"285844","o":1}