Основы программирования в Linux - Страница 80
Несмотря на то, что заново реализованное приложение для управления базой данных компакт-дисков не увидит свет до конца главы 7, его основы вы заложите в этой главе. Глава 6 посвящена curses, которые представляют собой вовсе не древнее проклятие, а библиотеку функций, предлагающих программный код высокого уровня для управления отображением на экране терминала. Попутно вы узнаете чуть больше о размышлениях прежних профи UNIX, познакомившись с основными принципами систем Linux и UNIX и понятием терминала. Низкоуровневый доступ, представленный в этой главе, быть может именно то, что вам нужно. Большая часть того, о чем мы пишем здесь, хорошо подходит для программ, выполняющихся в окне консоли, таких как эмуляторы терминала KDE's Konsole, GNOME's gnome-terminal или стандартный X11 xterm.
В этой главе вы, в частности, узнаете о:
□ чтении с терминала и записи на терминал;
□ драйверах терминала и общем терминальном интерфейсе (General Terminal Interface, GTI);
□ структуре типа
termios□ выводе терминала и базе данных
terminfo□ обнаружении нажатия клавиш.
Чтение с терминала и запись на терминал
В главе 3 вы узнали, что, когда программа запускается из командной строки, оболочка обеспечивает присоединение к ней стандартных потоков ввода и вывода. Вы получаете возможность взаимодействия с пользователем простым применением подпрограмм
getcharprintfВ упражнении 5.1 в программе menu1.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. Функция
maingetchoicemenuint main() { int choice = 0; do { choice = getchoice("Please select an action", menu); printf("You have chosen: %cn", choice); } while (choice != 'q'); exit(0);}3. Теперь важный фрагмент кода — функция, которая и выводит на экран меню и считывает ввод пользователя:
int getchoice(char *greet, char *choices[]) { int chosen = 0; int selected; char **option; do { printf("Choice: %sn", greet); option = choices; while (*option) { printf("%sn", *option); option++; } selected = getchar(); option = choices; while (*option) { if (selected == *option[0]) { chosen = 1; break; } option++; } if (!chosen) { printf("Incorrect choice, select againn"); } } while (!chosen); return selected;}Как это работает
Функция
getchoicegreetchoicesgetcharКогда вы откомпилируете и выполните программу, то обнаружите, что она ведет себя не так, как ожидалось. Для того чтобы продемонстрировать возникающую проблему, далее приведен вариант диалога на экране терминала.
$ ./menu1Choice: Please select an actiona — add new recordd — delete recordq — quitaYou have chosen: aChoice: Please select an actiona — add new recordd — delete recordq — quitIncorrect choice, select againChoice: Please select an actionа — add new recordd — delete recordq — quitqYou have chosen: q $Для того чтобы сделать выбор, пользователь должен последовательно нажать клавиши <А>, ,
Сравнение канонического и неканонического режимов
Обе эти проблемы тесно связаны. По умолчанию ввод терминала не доступен программе до тех пор, пока пользователь не нажмет клавишу