Книга: Основы программирования в Linux
Сравнение канонического и неканонического режимов
Сравнение канонического и неканонического режимов
Обе эти проблемы тесно связаны. По умолчанию ввод терминала не доступен программе до тех пор, пока пользователь не нажмет клавишу <Enter> или <Return>. В большинстве случаев это достоинство, поскольку данный способ позволяет пользователю корректировать ошибки набора с помощью клавиш <Backspace> или <Delete>. Только когда он остается доволен увиденным на экране, пользователь нажимает клавишу <Enter>, чтобы ввод стал доступен программе.
Такое поведение называется каноническим или стандартным режимом. Весь ввод обрабатывается как последовательность строк. Пока строка ввода не завершена (обычно с помощью нажатия клавиши <Enter>), интерфейс терминала управляет всеми нажатыми клавишами, включая <Backspace>, и приложение не может считать ни одного символа.
Прямая противоположность — неканонический режим, в котором приложение получает больше возможностей контроля над обработкой вводимых символов. Мы еще вернемся к этим двум режимам немного позже в этой главе.
Помимо всего прочего, обработчик терминала в ОС Linux помогает превращать символы прерываний в сигналы (например, останавливающие выполнение программы, когда вы нажмете комбинацию клавиш <Ctrl>+<C>), он также может автоматически выполнить обработку нажатых клавиш <Backspace> и <Delete> и вам не придется реализовывать ее в каждой написанной вами программе. О сигналах вы узнаете больше в главе 11.
Итак, что же происходит в данной программе? ОС Linux сохраняет ввод до тех пор, пока пользователь не нажмет клавишу <Enter>, и затем передает в программу символ выбранного пункта меню и следом за ним код клавиши <Enter>. Каждый раз, когда вы вводите символ пункта меню, программа вызывает функцию getchar
, обрабатывает символ и снова вызывает getchar
, немедленно возвращающую символ клавиши <Enter>.
Символ, который на самом деле видит программа, — это не символ ASCII возврата каретки CR (десятичный код 13, шестнадцатеричный 0D), а символ перевода строки LF (десятичный код 10, шестнадцатеричный 0A). Так происходит потому, что на внутреннем уровне ОС Linux (как и UNIX) всегда применяет перевод строки для завершения текстовых строк, т. е. в отличие от других ОС, таких как MS-DOS, использующих комбинацию символов возврата каретки и перевода строки, ОС UNIX применяет, для обозначения новой строки только символ перевода строки. Если вводное или выводное устройство посылает или запрашивает и символ возврата каретки, в ОС Linux об этом заботится обработчик терминала. Если вы привыкли работать в MS-DOS или других системах, это может показаться странным, но одно из существенных преимуществ заключается в отсутствии в ОС Linux реальной разницы между текстовыми и бинарными файлами. Символы возврата каретки обрабатываются, только когда вы вводите или выводите их на терминал или некоторые принтеры и плоттеры.
Вы можете откорректировать основной недостаток вашей подпрограммы меню, просто игнорируя дополнительный символ перевода строки с помощью программного кода, подобного приведенному далее:
do {
selected = getchar();
} while (selected == 'n');
Он решает непосредственно возникшую проблему, и вы увидите вывод, подобный приведенному далее:
$ ./menu1
Choice: Please select an action
a — add new record
d — delete record
q — quit
a
You have chosen: a
Choice: Please select an action
a — add new record
d — delete record
q — quit
q
You have chosen: q $
Мы вернемся позже ко второй проблеме, связанной с необходимостью нажимать клавишу <Enter>, и более элегантному решению для обработки символа перевода строки.
- 8.1.4. Сравнение массивов
- 4.2 Сравнение SAN и NAS
- Сравнение C# и C++
- 3.2. Сравнение операционных систем
- Описание режимов работы
- Сравнение ценностных профилей партнеров
- Большое сравнение: Fedora, openSUSE, Ubuntu
- 12.2.3. Сравнение блоков памяти: memcmp()
- 13.2.3. Сравнение строк: strcoll() и strxfrm()
- Сравнение времени выполнения различных версий функции str_cli
- Сравнение различных систем межпроцессного взаимодействия
- Сравнение спин-блокировок и семафоров