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

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

Жанры

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

> cat $i

> done | p

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

Структура

p
аналогична структуре
vis
: основная процедура выполняет цикл по файлам, вызывая функцию
print
, выполняющуюся с каждым файлом:

/* p: print input in chunks (version 1) */

#include <stdio.h>

#define PAGESIZE 22

char *progname; /* program name for error message */

main(argc, argv)

 int argc;

 char *argv[];

{

 int i;

 FILE *fp, *efopen;

 progname = argv[0];

 if (argc ==1)

print(stdin, PAGESIZE);

 else

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

fp = efopen(argv[i], "r");

print(fp, PAGESIZE);

fclose(fp);

}

 exit(0);

}

Функция

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

FILE *efopen(file, mode) /* fopen file, die if can't */

 char *file, *mode;

{

 FILE *fp, *fopen;

 extern char *progname;

 if ((fp = fopen(file, mode)) != NULL)

return fp;

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

progname, file, mode);

 exit(1);

}

Мы испытали две версии программы

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

Непосредственное выполнение команды

p
осуществляется в
print
:

print(fp, pagesize) /* print fp in pagesize chunks */

 FILE *fp;

 int pagesize;

{

 static int lines = 0; /* number of lines so far */

 char buf[BUFSIZ];

 while (fgets(buf, sizeof buf, fp) != NULL)

if (++lines < pagesize)

fputs(buf, stdout);

else {

buf[strlen(buf)-1] = '\0';

fputs(buf, stdout);

fflush(stdout);

ttyin;

lines = 0;

}

}

Мы

использовали здесь
BUFSIZ
, который определен в
<stdio.h>
как размер буфера входного потока. Функция
fgets(buf, size, fp)
выбирает следующую строку входного потока из
fp
до символа перевода строки (включая его) в буфер и добавляет завершающий символ
\0
. Копируется на более
size - 1
символов. По достижении конца файла возвращается
NULL
. (Конструкция
fgets
оставляет желать лучшего: она возвращает
buf
вместо счетчика символов и, кроме того, выдает предупреждение о том, что входная строка была слишком длинной. Символы не потеряны, но вы должны взглянуть на
buf
, чтобы понять, что в самом деле случилось.)

Функция

strlen
возвращает длину строки, поэтому мы можем отбросить завершающий символ перевода строки последней входной строки. После вызова
fputs(buf, fp)
строка
buf
записана в файл
fp
. При вызове
fflush
в конце страницы происходит вывод буферизованного выходного текста.

Считывание ответа пользователя в конце каждой страницы возложено на функцию

ttyin
. Функция
ttyin
не может читать стандартный входной поток, тогда как
p
должна выполняться, даже если входной поток поступает из файла или конвейера. Чтобы справиться с этим, программа открывает файл
/dev/tty
, которому поставлен в соответствие пользовательский терминал при любом переключении стандартного входного потока. Приведенная ниже функция
ttyin
возвращает первую букву ответа, но здесь это свойство не используется.

ttyin /* process response from /dev/tty (version 1) */

{

 char buf[BUFSIZ];

 FILE *efopen;

 static FILE *tty = NULL;

 if (tty == NULL)

tty = efopen("/dev/tty", "r");

 if (fgets(buf, BUFSIZ, tty) == NULL || buf[0] == 'q')

exit(0);

 else /* ordinary line */

return buf[0];

}

Указатель на файл

devtty
описан как статический, так что его значение сохраняется от одного вызова
ttyin
до другого; файл
/dev/tty
открывается только при первом вызове.

Очевидно, есть дополнительные средства, которые без особых усилий можно ввести в

p
, однако наша первая версия этой программы только печатает 22 строки и ждет следующей порции. Прошло немало времени, прежде чем в нее были добавлены другие средства, но в настоящее время ими мало кто пользуется. В частности, весьма простое дополнение ввод переменной
pagesize
для хранения числа строк на странице. Значение переменной можно установить из командной строки

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

Отмороженный 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
рейтинг книги
Сводный гад