Главная » Просмотр файлов » Керниган и Ритчи - Язык программирования Си

Керниган и Ритчи - Язык программирования Си (793773), страница 42

Файл №793773 Керниган и Ритчи - Язык программирования Си (Керниган и Ритчи - Язык программирования Си) 42 страницаКерниган и Ритчи - Язык программирования Си (793773) страница 422019-04-24СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 42)

Реализация функций fopen и getcТеперь на примере функций fopen и getc из стандартной библиотеки покажем, как описанные выше частисогласуются друг с другом.Напомним, что файлы в стандартной библиотеке описываются файловыми указателями, а не дескрипторами.Указатель файла — это указатель на структуру, содержащую информацию о файле: указатель на буфер,позволяющий читать файл большими кусками; число незанятых байтов буфера; указатель на следующуюпозицию в буфере; дескриптор файла; флажки, описывающие режим (чтение/запись), ошибочные состоянияи т. д.Структура данных, описывающая файл, содержится в <stdio.h>, который необходимо включать (спомощью #include) в любой исходный файл, если в том осуществляется стандартный ввод-вывод. Этот жезаголовочный файл включен и в исходные тексты библиотеки ввода-вывода.В следующем фрагменте, типичном для файла <stdio.h>, имена, используемые только в библиотечныхфункциях, начинаются с подчеркивания.

Это сделано для того, чтобы они случайно не совпали с именами,фигурирующими в программе пользователя. Такое соглашение соблюдается во всех программах стандартнойбиблиотеки.#define#define#define#defineNULL ОEOF (-1)BUFSIZ 1024OPEN_MAX 20 /* max число одновременно открытых файлов */typedef struct _iobuf {int cnt; /* количество оставшихся символов */char *ptr; /* позиция следующего символа */char *base; /* адрес буфера */int flag; /* режим доступа */int fd; /* дескриптор файла */} FILE;extern FILE _iob[OPEN_MAX];#define stdin (&iob[0])#define stdout (&_iob[1])#define stderr (&_iob[2])enum _flags {_READ =01, /* файл открыт на чтение */_WRITE = 02, /* файл открыт на запись */_UNBUF = 04, /* файл не буферизуется */_EOF = 010, /* в данном файле встретился EOF */_ERR = 020 /* в данном файле встретилась ошибка */};int _fillbuf(FILE *);int _flushbuf(int, FILE *);#define feof(p) (((p)->flag & _EOF) != 0)#define ferror(p) (((p)->flag & _ERR) != 0)#define fileno(p) ((p)->fd)#define getc(p) (--(p)->cnt >= 0 \? (unsigned char) *(p)->ptr++ : _fillbuf(p))#define putc(x.p) (--(p)->cnt >= 0 \? *(p)->ptr++ = (x) : _flushbuf((x),p))#define getchar() getc(stdin)#define putchar(x) putc((x), stdout)Макрос getc обычно уменьшает счетчик числа символов, находящихся в буфере, и возвращает символ,после чего приращивает указатель на единицу.

(Напомним, что длинные #define с помощью обратнойнаклонной черты можно продолжить на следующих строках.) Когда значение счетчика становитсяотрицательным, getc вызывает _fillbuf, чтобы снова заполнить буфер, инициализировать содержимоеструктуры и выдать символ.

Типы возвращаемых символов приводятся к unsigned; это гарантирует, что всеони будут положительными.Хотя в деталях ввод-вывод здесь не рассматривается, мы все же привели полное определение putc. Сделаноэто, чтобы показать, что она действует во многом так же, как и getc, вызывая функцию _flushbuf, когдабуфер полон. В тексте имеются макросы, позволяющие получать доступ к флажкам ошибки и конца файла, атакже к его дескриптору.Теперь можно написать функцию fopen. Большая часть инструкций fopen относится к открытию файла, ксоответствующему его позиционированию и к установке флажковых битов, предназначенных для индикациитекущего состояния.

Сама fopen не отводит места для буфера; это делает _fillbuf при первом чтениифайла.#include <fcntl.h>#include "syscalls.h"#define PERMS 0666 /* RW для собственника, группы и проч. *//* fopen: открывает файл, возвращает файловый указатель */FILE *fopen(char *name, char *mode){int fd;FILE *fp;if (*mode != 'r' && *mode != 'w' && *mode != 'a')return NULL;for (fp = _iob; fp < _iob + OPEN_MAX; fp++)if ((fp->flag & (_READ | _WRITE)) == 0)break; /* найдена свободная позиция*/if (fp >= _iob + OPEN_MAX) /* нет свободной позиции */return NULL;if (*mode == 'w' )fd = creat(name, PERMS);else if (*mode == 'a' ) {if ((fd = open(name, O_WRONLY, 0)) == -1)fd = creat(name, PERMS);lseek(fd, 0L, 2);} elsefd = open(name, O_RDONLY, 0);if (fd == -1) /* невозможен доступ по имени name */return NULL;fp->fd = fd;fp->cnt = 0;fp->base = NULL;fp->flag = (*mode == 'r' ) ? _READ : _WRITE;return fp;}Приведенная здесь версия fopen реализует не все режимы доступа, оговоренные стандартом; но, мыдумаем, их реализация в полном объеме ненамного увеличит длину программы.

Наша fopen не распознаетбуквы b, сигнализирующей о бинарном вводе-выводе (поскольку в системах UNIX это не имеет смысла), изнака +, указывающего на возможность одновременно читать и писать.Для любого файла в момент первого обращения к нему с помощью макровызова getc счетчик cnt равеннулю. Следствием этого будет вызов _fillbuf. Если выяснится, что файл на чтение не открыт, то функция_fillbuf немедленно возвратит EOF. В противном случае она попытается запросить память для буфера(если чтение должно быть с буферизацией).После получения области памяти для буфера _fillbuf обращается к read, чтобы его наполнить,устанавливает счетчик и указатели и возвращает первый символ из буфера. В следующих обращениях_fillbuf обнаружит, что память для буфера уже выделена.#include "syscalls.h"/* _fillbuf: запрос памяти и заполнение буфера */int _fillbuf(FILE *fp){int bufsize;if ((fp->flag&(_READ | _EOF | _ERR)) != _READ)return EOF;bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ;if (fp->base == NULL) /* буфера еще нет */if ((fp->base = (char *) malloc(bufsize)) == NULL)return EOF; /* нельзя получить буфер */fp->ptr = fp->base;fp->cnt = read(fp->fd, fp->ptr, bufsize);if (--fp->cnt < 0) {if (fp->cnt == -1)fp->flag |= _EOF;elsefp->flag |= _ERR;fp->cnt = 0;return EOF;}return (unsigned char) *fp->ptr++;}Единственное, что осталось невыясненным, — это каким образом организовать начало счета.

Массив _iobследует определить и инициализировать так, чтобы перед тем как программа начнет работать, в нем ужебыла информация о файлах stdin, stdout и stderr.FILE _iob[OPEN_MAX] = { /*{ 0, (char *) 0, (char{ 0, (char *) 0, (char{ 0, (char *) 0, (char};stdin, stdout, stderr: */*) 0, _READ, 0 },*) 0, _WRITE, 1 },*) 0, _WRITE | _UNNBUF, 2 }Инициализация flag как части структуры показывает, что stdin открыт на чтение, stdout — на запись, astderr — на запись без буферизации.Упражнение 8.2. Перепишите функции fopen и _fillbuf, работая с флажками как с полями, а не спомощью явных побитовых операций. Сравните размеры и скорости двух вариантов программ.Упражнение 8.3.

Разработайте и напишите функции _flushbuf, fflush и fclose.Упражнение 8.4. Функция стандартной библиотекиint fseek(FILE *fp, long offset, int origin)идентична функции lseek с теми, однако, отличиями, что fp — это файловый указатель, а не дескриптор, ивозвращает она значение int, означающее состояние файла, а не позицию в нем. Напишите свою версиюfseek.

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

д.). Аналогичной командойв MS-DOS является dir.Так как в системе UNIX каталог — это тоже файл, функции ls, чтобы добраться до имен файлов, нужно толькоего прочитать. Но чтобы получить другую информацию о файле (например узнать его размер), необходимовыполнить системный вызов.

В других системах (в MS-DOS, например) системным вызовом приходитсяпользоваться даже для получения доступа к именам файлов. Наша цель — обеспечить доступ к информациипо возможности системно-независимым способом несмотря на то, что реализация может быть существенносистемно-зависима.Проиллюстрируем сказанное написанием программы fsize. Функция fsize — частный случай программыls; она печатает размеры всех файлов, перечисленных в командной строке. Если какой-либо из файлов самявляется каталогом, то, чтобы получить информацию о нем, fsize обращается сама к себе.

Если аргументовв командной строке нет, то обрабатывается текущий каталог.Для начала вспомним структуру файловой системы в UNIXe. Каталог — это файл, содержащий список именфайлов и некоторую информацию о том, где они расположены. "Место расположения" — это индекс,обеспечивающий доступ в другую таблицу, называемую "списком узлов inode". Для каждого файла имеетсясвой inode, где собрана вся информация о файле, за исключением его имени. Каждый элемент каталогасостоит из двух частей: из имени файла и номера узла inode.К сожалению, формат и точное содержимое каталога не одинаковы в разных версиях системы. Поэтому,чтобы переносимую компоненту отделить от непереносимой, разобьем нашу задачу на две. Внешнийуровень определяет структуру, названную Dirent, и три подпрограммы opendir, readdir и closedir; врезультате обеспечивается системно-независимый доступ к имени и номеру узла inode каждого элементакаталога.

Мы будем писать программу fsize, рассчитывая на такой интерфейс, а затем покажем, какреализовать указанные функции для систем, использующих ту же структуру каталога, что и Version 7 и SystemV UNIX. Другие варианты оставим для упражнений.Структура Dirent содержит номер узла inode и имя. Максимальная длина имени файла равна NAME_MAX —это значение системно-зависимо. Функция opendir возвращает указатель на структуру, названную DIR (поаналогии с FILE), которая используется функциями readdir и closedir.

Характеристики

Тип файла
PDF-файл
Размер
2,25 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7027
Авторов
на СтудИзбе
260
Средний доход
с одного платного файла
Обучение Подробнее