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

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

Жанры

Основы программирования в 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 с самого начала создавалась, как многопользовательская система, включающая, как правило, множество терминалов, как непосредственно подсоединенных, так и подключенных по сети, как вы сможете определить тот терминал, который следует использовать?

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

Вечная Война. Книга II

Винокуров Юрий
2. Вечная война.
Фантастика:
юмористическая фантастика
космическая фантастика
8.37
рейтинг книги
Вечная Война. Книга II

Развод с драконом. Отвергнутая целительница

Шашкова Алена
Фантастика:
фэнтези
4.75
рейтинг книги
Развод с драконом. Отвергнутая целительница

Погранец

Поселягин Владимир Геннадьевич
2. Решала
Фантастика:
фэнтези
боевая фантастика
альтернативная история
5.00
рейтинг книги
Погранец

Двойник Короля 8

Скабер Артемий
8. Двойник Короля
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Двойник Короля 8

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

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

Кодекс Императора IV

Сапфир Олег
4. Кодекс Императора
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Императора IV

Господин из завтра. Тетралогия.

Махров Алексей
Фантастика:
альтернативная история
8.32
рейтинг книги
Господин из завтра. Тетралогия.

Неправильный лекарь. Том 2

Измайлов Сергей
2. Неправильный лекарь
Фантастика:
городское фэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Неправильный лекарь. Том 2

Изгой Проклятого Клана. Том 3

Пламенев Владимир
3. Изгой
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Изгой Проклятого Клана. Том 3

Телохранитель Генсека. Том 4

Алмазный Петр
4. Медведев
Фантастика:
попаданцы
альтернативная история
6.00
рейтинг книги
Телохранитель Генсека. Том 4

Третий. Том 2

INDIGO
2. Отпуск
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 2

На границе империй. Том 10. Часть 1

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 1

Наследник

Назимов Константин Геннадьевич
3. Травник
Фантастика:
фэнтези
6.80
рейтинг книги
Наследник

Наша навсегда

Зайцева Мария
2. Наша
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Наша навсегда