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

Несмотря на то, что заново реализованное приложение для управления базой данных компакт-дисков не увидит свет до конца главы 7, его основы вы заложите в этой главе. Глава 6 посвящена curses, которые представляют собой вовсе не древнее проклятие, а библиотеку функций, предлагающих программный код высокого уровня для управления отображением на экране терминала. Попутно вы узнаете чуть больше о размышлениях прежних профи UNIX, познакомившись с основными принципами систем Linux и UNIX и понятием терминала. Низкоуровневый доступ, представленный в этой главе, быть может именно то, что вам нужно. Большая часть того, о чем мы пишем здесь, хорошо подходит для программ, выполняющихся в окне консоли, таких как эмуляторы терминала KDE's Konsole, GNOME's gnome-terminal или стандартный X11 xterm.

В этой главе вы, в частности, узнаете о:

□ чтении с терминала и записи на терминал;

□ драйверах терминала и общем терминальном интерфейсе (General Terminal Interface, GTI);

□ структуре типа

termios
;

□ выводе терминала и базе данных

terminfo
;

□ обнаружении нажатия клавиш.

Чтение с терминала и запись на терминал

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

getchar
и
printf
для чтения из стандартного потока ввода и записи в стандартный поток вывода.

В упражнении 5.1 в программе menu1.c вы попытаетесь переписать на языке С подпрограммы формирования меню, использующие только эти две функции.

Упражнение 5.1. Подпрограммы формирования меню на языке C

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

getchoice
:

#include <stdio.h>

#include <stdlib.h>

char *menu[] = {

 "a — add new record", "d — delete record", "q - quit", NULL,

};

int getchoice(char *greet, char *choices[]);

2. Функция

main
вызывает функцию
getchoice
с образцом пунктов меню
menu
:

int main() {

 int choice = 0;

 do {

  choice = getchoice("Please select an action", menu);

  printf("You have chosen: %c\n", choice);

 } while (choice != 'q');

 exit(0);

}

3. Теперь важный фрагмент кода — функция, которая и выводит на экран меню и считывает ввод пользователя:

int getchoice(char *greet, char *choices[]) {

 int chosen = 0;

 int selected;

 char **option;

 do {

  printf("Choice: %s\n", greet);

  option = choices;

  while (*option) {

   printf("%s\n", *option);

   option++;

  }

  selected = getchar();

  option = choices;

  while (*option) {

   if (selected == *option[0]) {

    chosen = 1;

    break;

   }

   option++;

  }

  if (!chosen) {

   printf("Incorrect choice, select again\n");

  }

 } while (!chosen);

 return selected;

}

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

Функция

getchoice
выводит на экран приглашение для ввода
greet
и меню
choices
и просит пользователя ввести первый символ выбранного пункта. Далее выполняется цикл до тех пор, пока функция
getchar
не вернет символ, совпадающий с первой буквой одного из элементов массива option.

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

$ <b>./menu1</b>

Choice: Please select an action

a — add new record

d — delete record

q — quit

<b>a</b>

You have chosen: a

Choice: Please select an action

a — add new record

d — delete record

q — quit

Incorrect choice, select again

Choice: Please select an action

а — add new record

d — delete record

q — quit

<b>q</b>

You have chosen: q $

Для того чтобы сделать выбор, пользователь должен последовательно нажать клавиши <А>, <Enter>, <Q>, <Enter>. Здесь возникают, как минимум, две проблемы; самая серьезная заключается в том, что вы получаете сообщение "Incorrect choice" ("Неверный выбор") после каждого корректного выбора. Кроме того, вы еще должны нажать клавишу <Enter> (или <Return>), прежде чем программа считает введенные данные.

Сравнение канонического и неканонического режимов

Обе эти проблемы тесно связаны. По умолчанию ввод терминала не доступен программе до тех пор, пока пользователь не нажмет клавишу <Enter> или <Return>. В большинстве случаев это достоинство, поскольку данный способ позволяет пользователю корректировать ошибки набора с помощью клавиш <Backspace> или <Delete>. Только когда он остается доволен увиденным на экране, пользователь нажимает клавишу <Enter>, чтобы ввод стал доступен программе.

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