русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Упражнение 8-2


Дата добавления: 2015-01-16; просмотров: 476; Нарушение авторских прав


---------------

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

LSEEK и наоборот. напишите каждую функцию через другую.

 

 

Пример - реализация функций FOPEN и GETC

 

 

Давайте теперь на примере реализации функций FOPEN и

GETC из стандартной библиотеки подпрограмм продемонстрируем,

как некоторые из описанных элементов объединяются вместе.

Напомним, что в стандартной библиотеке файлы описыватся

посредством указателей файлов, а не дескрипторов. Указатель

файла является указателем на структуру, которая содержит

несколько элементов информации о файле: указатель буфера,

чтобы файл мог читаться большими порциями; счетчик числа

символов, оставшихся в буфере; указатель следующей позиции

символа в буфере; некоторые признаки, указывающие режим чте-

ния или записи и т.д.; дескриптор файла.

Описывающая файл структура данных содержится в файле

STDIO.H, который должен включаться (посредством #INCLUDE) в

любой исходный файл, в котором используются функции из стан-

дартной библиотеки. Он также включается функциями этой биб-

лиотеки. В приводимой ниже выдержке из файла STDIO.H имена,

предназначаемые только для использования функциями библиоте-

ки, начинаются с подчеркивания, с тем чтобы уменьшить веро-

ятность совпадения с именами в программе пользователя.

 

DEFINE _BUFSIZE 512

DEFINE _NFILE 20 /*FILES THAT CAN BE HANDLED*/

TYPEDEF STRUCT _IOBUF \(

CHAR *_PTR; /*NEXT CHARACTER POSITION*/

INT _CNT; /*NUMBER OF CHARACTERS LEFT*/

CHAR *_BASE; /*LOCATION OF BUFFER*/

INT _FLAG; /*MODE OF FILE ACCESS*/

INT _FD; /*FILE DESCRIPTOR*/

) FILE;

XTERN FILE _IOB[_NFILE];

 

DEFINE STDIN (&_IOB[0])

DEFINE STDOUT (&_IOB[1])

DEFINE STDERR (&_IOB[2])

 

DEFINE _READ 01 /* FILE OPEN FOR READING */



DEFINE _WRITE 02 /* FILE OPEN FOR WRITING */

DEFINE _UNBUF 04 /* FILE IS UNBUFFERED */

DEFINE _BIGBUF 010 /* BIG BUFFER ALLOCATED */

DEFINE _EOF 020 /* EOF HAS OCCURRED ON THIS FILE */

DEFINE _ERR 040 /* ERROR HAS OCCURRED ON THIS FILE */

DEFINE NULL 0

DEFINE EOF (-1)

 

DEFINE GETC(P) (--(P)->_CNT >= 0 \

? *(P)->_PTR++ & 0377 : _FILEBUF(P))

DEFINE GETCHAR() GETC(STDIN)

 

DEFINE PUTC(X,P) (--(P)->_CNT >= 0 \

? *(P)->_PTR++ = (X) : _FLUSHBUF((X),P))

DEFINE PUTCHAR(X) PUTC(X,STDOUT)

 

В нормальном состоянии макрос GETC просто уменьшает

счетчик, передвигает указатель и возвращает символ. (Если

определение #DEFINE слишком длинное, то оно продолжается с

помощью обратной косой черты). Если однако счетчик становит-

ся отрицательным, то GETC вызывает функцию _FILEBUF, которая

снова заполняет буфер, реинициализирует содержимое структуры

и возвращает символ. Функция может предоставлять переносимый

интерфейс и в то же время содержать непереносимые конструк-

ции: GETC маскирует символ числом 0377, которое подавляет

знаковое расширение, осуществляемое на PDP-11, и тем самым

гарантирует положительность всех символов.

Хотя мы не собираемся обсуждать какие-либо детали, мы

все же включили сюда определение макроса PUTC, для того что-

бы показать, что она работает в основном точно также, как и

GETC, обращаясь при заполнении буфера к функции _FLUSHBUF.

Теперь может быть написана функция FOPEN. Большая часть

программы функции FOPEN связана с открыванием файла и распо-

ложением его в нужном месте, а также с установлением битов

признаков таким образом, чтобы они указывали нужное состоя-

ние. Функция FOPEN не выделяет какой-либо буферной памяти;

это делается функцией _FILEBUF при первом чтении из файла.

 

#INCLUDE <STDIO.H>

#DEFINE PMODE 0644 /*R/W FOR OWNER;R FOR OTHERS*/

FILE *FOPEN(NAME,MODE) /*OPEN FILE,RETURN FILE PTR*/

REGISTER CHAR *NAME, *MODE;

\(

REGISTER INT FD;

REGISTER FILE *FP;

IF(*MODE !='R'&&*MODE !='W'&&*MODE !='A') \(

FPRINTF(STDERR,"ILLEGAL MODE %S OPENING %S\N",

MODE,NAME);

EXIT(1);

\)

FOR (FP=_IOB;FP<_IOB+_NFILE;FP++)

IF((FP->_FLAG & (_READ \! _WRITE))==0)

BREAK; /*FOUND FREE SLOT*/

IF(FP>=_IOB+_NFILE) /*NO FREE SLOTS*/

RETURN(NULL);

IF(*MODE=='W') /*ACCESS FILE*/

FD=CREAT(NAME,PMODE);

ELSE IF(*MODE=='A') \(

IF((FD=OPEN(NAME,1))==-1)

FD=CREAT(NAME,PMODE);

LSEEK(FD,OL,2);

\) ELSE

FD=OPEN(NAME,0);

IF(FD==-1) /*COULDN'T ACCESS NAME*/

RETURN(NULL);

FP->_FD=FD;

FP->_CNT=0;

FP->_BASE=NULL;

FP->_FLAG &=(_READ \! _WRITE);

FP->_FLAG \!=(*MODE=='R') ? _READ : _WRITE;

RETURN(FP);

\)

 

 

Функция _FILEBUF несколько более сложная. Основная труд-

ность заключается в том, что _FILEBUF стремится разрешить

доступ к файлу и в том случае, когда может не оказаться дос-

таточно места в памяти для буферизации ввода или вывода. ес-

ли пространство для нового буфера может быть получено обра-

щением к функции CALLOC, то все отлично; если же нет, то

_FILEBUF осуществляет небуферизованный ввод/ вывод, исполь-

зуя отдельный символ, помещенный в локальном массиве.

 

#INCLUDE <STDIO.H>

_FILLBUF(FP) /*ALLOCATE AND FILL INPUT BUFFER*/

REGISTER FILE *FP;

(

STATIC CHAR SMALLBUF(NFILE);/*FOR UNBUFFERED 1/0*/

CHAR *CALLOC();

IF((FR->_FLAG&_READ)==0\!\!(FP->_FLAG&(EOF\!_ERR))\!=0

RETURN(EOF);

WHILE(FP->_BASE==NULL) /*FIND BUFFER SPACE*/

IF(FP->_FLAG & _UNBUF) /*UNBUFFERED*/

FP->_BASE=&SMALLBUF[FP->_FD];

ELSE IF((FP->_BASE=CALLOC(_BUFSIZE,1))==NULL)

FP->_FLAG \!=_UNBUF; /*CAN'T GET BIG BUF*/

ELSE

FP->_FLAG \!=_BIGBUF; /*GOT BIG ONE*/

FP->_PTR=FP->_BASE;

FP->_CNT=READ(FP->_FD, FP->_PTR,

FP->_FLAG & _UNBUF ? 1 : _BUFSIZE);

FF(--FP->_CNT<0) \(

IF(FP->_CNT== -1)

FP->_FLAG \! = _EOF;

ELSE

FP->_FLAG \! = _ ERR;

FP->_CNT = 0;

RETURN(EOF);

\)

RETURN(*FP->_PTR++ & 0377); /*MAKE CHAR POSITIVE*/

)

 

При первом обращении к GETC для конкретного файла счетчик

оказывается равным нулю, что приводит к обращению к

_FILEBUF. Если функция _FILEBUF найдет, что этот файл не от-

крыт для чтения, она немедленно возвращает EOF. В противном

случае она пытается выделить большой буфер, а если ей это не

удается, то буфер из одного символа. При этом она заносит в

_FLAG соответствующую информацию о буферизации.

Раз буфер уже создан, функция _FILEBUF просто вызывает

функцию READ для его заполнения, устанавливает счетчик и

указатели и возвращает символ из начала буфера.

Единственный оставшийся невыясненным вопрос состоит в

том, как все начинается. Массив _IOB должен быть определен и

инициализирован для STDIN, STDOUT и STDERR:

 

FILE _IOB[NFILE] = \(

(NULL,0,_READ,0), /*STDIN*/

(NULL,0,NULL,1), /*STDOUT*/

(NULL,0,NULL,_WRITE \! _UNBUF,2) /*STDERR*/

);

 

Из инициализации части _FLAG этого массива структур видно,

что файл STDIN предназначен для чтения, файл STDOUT - для

записи и файл STDERR - для записи без использования буфера.

 



<== предыдущая лекция | следующая лекция ==>
 | Упражнение 8-3


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.185 сек.