Чтение онлайн

на главную - закладки

Жанры

Основы программирования в 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>, и более элегантному решению для обработки символа перевода строки.

Обработка перенаправленного вывода

Для программ, выполняющихся в ОС Linux, даже интерактивных, характерно перенаправление своего ввода и вывода как в файлы, так и в другие программы. Давайте рассмотрим поведение вашей программы при перенаправлении ее вывода в файл.

$ ./menu1 > file

a

q

$

Такой результат можно было бы считать успешным, потому что вывод перенаправлен в файл вместо терминала. Однако бывают случаи, когда нужно помешать такому исходу событий или отделить приглашения или подсказки, которые пользователь должен видеть, от остального вывода, благополучно перенаправляемого в файл.

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

isatty
. Вы просто передаете ему корректный дескриптор файла, и он проверяет, связан ли этот дескриптор в данный момент с терминалом.

#include <unistd.h>

int isatty(int fd);

Системный вызов

isatty
возвращает 1, если открытый дескриптор файла
fd
связан с терминалом, и 0 в противном случае.

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

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

Что вы собираетесь делать, если стандартный вывод

stdout
перенаправлен? Просто завершить программу — не слишком хорошо, потому что у пользователя нет возможности выяснить, почему программа аварийно завершила выполнение. Вывод сообщения в
stdout
тоже не поможет, поскольку оно будет перенаправлено с терминала. Единственное решение — записать сообщение в стандартный поток ошибок
stderr
, который не перенаправляется командой оболочки
> file
(упражнение 5.2).

Упражнение 5.2. Проверка для выявления перенаправления вывода

Внесите следующие изменения в директивы включения заголовочных файлов и функцию main программы menu1.с из упражнения 5.1. Назовите новый файл menu2.c.

#include <unistd.h>

...

int main {

 int choice = 0;

 if (!isatty(fileno(stdout))) {

fprintf(stderr, "You are not a terminal!\n");

exit(1);

 }

 do {

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

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

 } while (choice != 'q');

 exit(0);

}

Теперь посмотрите на следующий пример вывода:

$ ./menu2

Choice: Please select an action

a — add new record

d — delete record

q — quit

q

You have chosen: q $ ./menu2 > file

You are not a terminal! $

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

В новом фрагменте программного кода функция

isatty
применяется для проверки связи стандартного вывода с терминалом и прекращения выполнения программы при отсутствии этой связи. Это тот же самый тест, который командная оболочка использует для решения, нужно ли выводить строки приглашения. Возможно и довольно обычно перенаправление и
stdout
, и
stderr
с терминала на другое устройство. Вы можете направить поток ошибок в другой файл:

$ ./menu2 >file 2>file.error

$

или объединить оба выводных потока в одном файле:

$ ./menu2 >file 2>&1

$

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

Диалог с терминалом

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

stdout
и
stderr
. Это можно сделать, непосредственно считывая данные с терминала и прямо записывая данные на терминал. Поскольку ОС Linux с самого начала создавалась, как многопользовательская система, включающая, как правило, множество терминалов, как непосредственно подсоединенных, так и подключенных по сети, как вы сможете определить тот терминал, который следует использовать?

Поделиться:
Популярные книги

Локки 4 Потомок бога

Решетов Евгений Валерьевич
4. Локки
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Локки 4 Потомок бога

Егерь. Сердце стаи. Книга 5

Скиба Николай
5. Зверолов
Фантастика:
рпг
фэнтези
фантастика: прочее
попаданцы
6.80
рейтинг книги
Егерь. Сердце стаи. Книга 5

Газлайтер. Том 15

Володин Григорий Григорьевич
15. История Телепата
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Газлайтер. Том 15

Сильнейший Столп Империи. Книга 1

Ермоленков Алексей
1. Сильнейший Столп Империи
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 1

Тень Гегемона

Кард Орсон Скотт
2. Эндер Виггин. Сага теней
Фантастика:
научная фантастика
7.11
рейтинг книги
Тень Гегемона

Серые сутки

Сай Ярослав
4. Медорфенов
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Серые сутки

Ореховый посох

Скотт Роберт
1. Eldarn Trilogy
Фантастика:
фэнтези
6.25
рейтинг книги
Ореховый посох

Архивариус

alchoz
Проект «Поттер-Фанфикшн»
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Архивариус

iOS. Приемы программирования

Нахавандипур Вандад
Компьютеры и Интернет:
программирование
5.00
рейтинг книги
iOS. Приемы программирования

Лестница бога. Пенталогия

Киселев Юрий Львович
Вселенная EVE Online
Фантастика:
фэнтези
боевая фантастика
6.67
рейтинг книги
Лестница бога. Пенталогия

Эпоха Опустошителя. Том VII

Павлов Вел
7. Вечное Ристалище
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Эпоха Опустошителя. Том VII

Безмолвная

Герритсен Тесс
9. Джейн Риццоли и Маура Айлс
Детективы:
триллеры
8.81
рейтинг книги
Безмолвная

Медная шкатулка (сборник)

Рубина Дина Ильинична
Проза:
современная проза
7.50
рейтинг книги
Медная шкатулка (сборник)

"Фантастика 2023-139". Компиляция. Книги 1-20

Поселягин Владимир Геннадьевич
Фантастика 2023. Компиляция
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Фантастика 2023-139. Компиляция. Книги 1-20