- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 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, так что если один из файлов по каким-то причинам недоступен, сообщение найдет путь на терминал пользователя, а не исчезнет в программном канале или в выходном файле. (Стандартный поток диагностики был изобретен позднее, чем программные каналы: после того, как сообщения об ошибках стали исчезать при передаче через эти каналы.)