- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
UNIX — универсальная среда программирования - Брайан Керниган
Шрифт:
Интервал:
Закладка:
$ vis файл1 файл2 ...
будет просматривать эти именованные файлы вместо стандартного входного потока. Если же имен файлов в качестве аргументов нет, vis должна читать стандартный входной поток.
Возникает вопрос: как организовать чтение файлов, т.е. как связать имена файлов с операторами ввода вывода, реально читающими данные? Правила просты. Прежде чем быть прочитанным или записанным, файл должен быть открыт стандартной библиотечной функцией fopen. Последняя берет имя файла (например, temp или /etc/passwd), взаимодействует с ядром и возвращает обратно "внутреннее имя", которое используется при последующих операциях с данным файлом.
Внутреннее имя является на самом деле указателем (называемым указателем файла) на структуру, содержащую информацию о файле, такую, как расположение буфера, текущую позицию символа в буфере, режим чтения или записи и т.п. Эта структура определяется в файле <stdio.h> и имеет имя FILE. Описание указателя файла таково:
FILE *fp;
Оно означает, что fp — указатель на FILE, fopen возвращает указатель на FILE; в <stdio.h> имеется описание типа для fopen. Реальный вызов функции fopen:
char *name, *mode;
fr = fopen(name, mode);
Первый аргумент fopen представляет собой имя файла (строку символов). Второй аргумент также является символьной строкой, показывающей, как вы намереваетесь использовать файл; допустимые режимы: читать ("r"), писать ("w") или дописать ("а").
Если файл, который вы открыли для записи или дописывания, не существует, он создается, если это возможно. Открытие для записи существующего файла вызывает уничтожение старого содержимого. Попытка читать несуществующий файл считается ошибкой, так же как и попытка читать или писать файл без разрешения. При возникновении ошибки fopen возвращает значение несуществующего указателя NULL (которое обычно определяется в <stdio.h> как (char*)0).
Далее, нужен способ читать или писать файл после того, как он открыт. Есть несколько способов, из которых использование getc и putc самый простой. Функция getc выбирает из файла очередной символ:
с = getc(fp)
помещает в с следующий символ из файла, на который указывает fp. Эта функция возвращает EOF по достижении конца файла. Функция putc аналогична getc:
putc(c, fp)
помещает символ с в файл fp и возвращает с. Функции getc и putc возвращают EOF в случае ошибки.
Когда программа начинает выполняться, уже открыты три файла и имеются их указатели. Это стандартные потоки: входной, выходной и поток диагностики; соответствующие указатели называются stdin, stdout и stderr. Указатели на файлы описаны в <stdio.h> и могут использоваться там, где может быть объект типа FILE*. Они являются не переменными, а константами, так что им нельзя присвоить значения. Вызов getchar() есть getc(stdin), a putchar(c) есть putc(c, stdout). На самом деле все эти четыре "функции" определены в <stdio.h> как макрокоманды. Они выполняются быстрее обычных вызовов функций ввиду отсутствия накладных расходов по вызову функции для каждого символа (см. табл. 6.3 с некоторыми другими определениями из <stdio.h>).
stdin Стандартный входной поток stdout Стандартный выходной поток stderr Стандартный поток диагностики EOF Конец файла; обычно -1 NULL Несуществующий указатель; обычно 0 FILE Используется для описания указателей на файлы BUFSIZ Обычно размер буфера ввода вывода (часто 512 или 1024) getc(fp) Возвращает один символ из потока fp getchar() getc(stdin) putc(c,fp) Помещает символ с в поток fp putchar(c) putс(с,stdout) feof(fp) Не нуль, если достигнут конец файла для потока fp ferror(fp) Не нуль, если в потоке fp есть ошибка fileno(fp) Дескриптор файла для потока fp (см. гл. 7)Таблица 6.3: Некоторые определения из <stdio.h>
Теперь вернемся снова к нашей теме и напишем третью версию vis. Если есть аргументы командной строки, они обрабатываются в порядке очередности, если же аргументов нет, используется стандартный входной поток.
/* vis: make funny characters visible (version 3) */
#include <stdio.h>
#include <ctype.h>
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 %sn",
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 %sn",
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, так что если один из файлов по каким-то причинам недоступен, сообщение найдет путь на терминал пользователя, а не исчезнет в программном канале или в выходном файле. (Стандартный поток диагностики был изобретен позднее, чем программные каналы: после того, как сообщения об ошибках стали исчезать при передаче через эти каналы.)

