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



         

Пример - реализация функций FOPEN и GETC - часть 2


В нормальном состоянии макрос 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); }




Содержание  Назад  Вперед