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

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

Жанры

UNIX — универсальная среда программирования
Шрифт:

int strip = 0; /* 1 => discard special characters */

main(argc, argv)

 int argc;

 char *argv[];

{

 int i;

 FILE *fp;

 while (argc > 1 && argv[1][0] == '-') {

switch (argv[1][1]) {

case 's': /* -s: strip funny chars */

strip = 1;

break;

default:

fprintf(stderr, "%s: unknown arg %s\n",

argv[0], argv[1]);

exit(1);

}

argc--;

argv++;

 }

 if (argc == 1)

vis(stdin);

 else

 for (i = 1; i < argc; i++)

if ((fp=fopen(argv[i], "r")) == NULL) {

fprintf(stderr, "%s: can't open %s\n",

argv[0], argv[i]);

exit(1);

} else {

vis(fp);

fclose(fp);

}

 exit(0);

}

В

программе принято соглашение, по которому флаги стоят в начале списка аргументов. После обработки каждого флага
argv
и
argc
модифицируются так, что остальная часть программы не зависит от присутствия этого флага. Даже если
vis
распознает единственный флаг, мы написали программу в виде цикла, чтобы продемонстрировать единый способ обработки аргументов. В гл. 1 отмечалось, что программы UNIX обрабатывают флаги в произвольном порядке. Как одну из причин (помимо склонности к анархии) здесь можно назвать очевидную легкость написания программы разбора аргументов при любой модификации. Включение функции
getopt(3)
в некоторые системы является попыткой рационально объяснить ситуацию; вы можете ее исследовать, прежде чем писать собственную.

Процедура

vis
выводит на печать единственный файл:

vis(fp) /* make chars visible in FILE *fp */

 FILE *fp;

{

 int c;

 while ((с = getc(fp)) != EOF)

if (isascii(c) &&

(isprint(с) || c=='\n' || c=='\t' || c==' '))

putchar(c);

else if (!strip)

printf("\\%03o", c);

}

Функция

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

Функция

fclose
разрывает связь между указателем и внешним именем файла, установленную с помощью
fopen
, освобождая указатель для другого файла. Так как существует ограничение (около 20) на число файлов, которые одновременно могут быть открыты в программе, лучше всего закрывать уже не требующиеся вам файлы. Обычно выходной поток, выдаваемый любой стандартной библиотечной функцией, подобной
printf
,
putc
и т.д., для большей эффективности буферизуется так, чтобы его можно было писать большими фрагментами. (Исключение составляет выходной поток терминала, который, как правило, пишется по мере своего формирования или при печати символа перевода строки.) Применение
fclose
к выходному файлу инициирует выдачу последней буферизованной порции,
fclose
также вызывается автоматически для каждого открытого файла, когда программа выполняет
exit
или возвращается из
main
.

Стандартный поток

stderr
присваивается программе тем же способом, что и
stdin
и
stdout
. Информация, записанная в
stderr
, оказывается на терминале пользователя даже при изменении назначения стандартного выходного потока.
Vis
пишет свою диагностику в
stderr
вместо
stdout
, так что если один из файлов по каким-то причинам недоступен, сообщение найдет путь на терминал пользователя, а не исчезнет в программном канале или в выходном файле. (Стандартный поток диагностики был изобретен позднее, чем программные каналы: после того, как сообщения об ошибках стали исчезать при передаче через эти каналы.)

Мы решили, отчасти произвольно, что

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

Упражнение 6.5.

Напишите программу

printable
, которая печатает имя каждого аргумента-файла, содержащего только печатаемые символы; если в файле хранится любой непечатаемый символ, имя не печатается. printable полезна в ситуациях, подобных следующей:

$ pr `printable *` | lpr

Добавьте флаг

– v
, чтобы изменить смысл проверки на обратный, как в
grep
. Что следует делать, если среди аргументов нет имен файлов? Какой код завершения должна передавать
printable
при возврате?

6.4 Вывод на экран порциями: программа

p

До сих пор мы использовали cat для просмотра файлов. Но если файл длинный, а связь с системой высокоскоростная, cat выдает выходной файл слишком быстро, что затрудняет его чтение, даже если вы успеваете делать это с помощью ctl-s и ctl-q.

Очевидно, нужно иметь программу для печати файла небольшими удобными порциями, но такая программа не является стандартной, возможно, потому, что первоначальная система UNIX была написана в те времена, когда использовались терминалы "твердой копии" (печати на бумаге) и медленные линии связи. Поэтому наш следующий пример программа

p
, которая выводит файл по частям, занимающим полный экран, за один раз, ожидая ответа от пользователя после выдачи каждой порции прежде, чем начать очередной вывод (краткое имя
p
весьма удобно для программы, которая часто используется). Подобно другим программам,
p
читает или из файлов, поименованных, как аргументы, или из стандартного входного потока:

$ p vis.с

...

$ grep '#define' *.[ch] | p

...

$

Эту программу легче всего писать на Си; стандартные средства неудобны, когда происходит смешанный ввод из файла или конвейера и с терминала. Решение состоит в том, чтобы печатать входной поток небольшими порциями. Удобный размер порции 22 строки, что составляет немногим меньше, чем размер в 24 строки на большинстве видеотерминалов, и одну треть стандартной страницы в 66 строк. Простой способ подсказки пользователю не печатать последний символ перевода строки каждой порции. Курсор остановится на правом конце строки, а не на левой границе (новой строки). При нажатии клавиши RETURN выполняется перевод строки, и следующая строка появляется в нужном месте. Если пользователь печатает ctl-d или q в конце экрана, выполнение программы

p
заканчивается.

Мы не станем принимать специальных мер для вывода длинных строк. Мы также не будем беспокоиться о множестве файлов: просто перейдем от одного к другому без примечаний. Следующая команда

$ p имена файлов...

по своему действию аналогична команде

$ cat имена файлов... | p

Если нужны имена файлов, их можно добавить циклом

for
:

$ for i in имена файлов

> do

> echo $i:

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

Отмороженный 8.0

Гарцевич Евгений Александрович
8. Отмороженный
Фантастика:
постапокалипсис
рпг
аниме
5.00
рейтинг книги
Отмороженный 8.0

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

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

Ермак. Телохранитель

Валериев Игорь
2. Ермак
Фантастика:
альтернативная история
7.00
рейтинг книги
Ермак. Телохранитель

Матабар IV

Клеванский Кирилл Сергеевич
4. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар IV

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Идеальный мир для Лекаря 19

Сапфир Олег
19. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 19

Дочь моего друга

Тоцка Тала
2. Айдаровы
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Дочь моего друга

Свет Черной Звезды

Звездная Елена
6. Катриона
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Свет Черной Звезды

Кодекс Крови. Книга IV

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

Идеальный мир для Лекаря 22

Сапфир Олег
22. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 22

Попаданка в академии драконов 4

Свадьбина Любовь
4. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.47
рейтинг книги
Попаданка в академии драконов 4

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад