9. 贯穿案例:构建标准IO函数库
//mstdio.h
#ifndef __MSTDIO_H__ #define __MSTDIO_H__ #include <unistd.h> #define MEOF -1 //定义文件末尾标志 //文件读写模式 enum mode{READ, WRITE, APPEND}; //MFILE结构体 typedef struct { int _fd; char* _buffer; //缓冲区 char* _nextc; //下一个字符 int _mode; //读写模式 off_t _left; //剩余多少字节(对于读表示缓冲区中未读的 //字节数对于写,表示缓冲区还剩的空闲空间) }MFILE, *PMFILE; extern MFILE* mfopen(const char* const pathname, const char* const mode); extern int mfclose(MFILE* fp); extern void mfflush(MFILE* fp); extern MFILE* mfdopen(int fd, const char* const mode); extern int mfgetc(MFILE* fp); extern int mfputc(int character, MFILE* fp); extern int mungetc(int character, MFILE* fp); extern char* mfgets(char* buff, int size, MFILE* fp); extern int mfputs(char* buff, MFILE* fp); extern size_t mfread(void* buff, size_t size, size_t counter, MFILE* fp); extern size_t mfwrite(void* buff, size_t size, size_t counter, MFILE* fp); #endif
//mstdio.c
#include "mstdio.h" #include <assert.h> #include <string.h> #include <fcntl.h> #include <malloc.h> #define BUFFER_LEN 1024 MFILE* mfopen(const char* const pathname, const char* const mode) { int fd; if(!strcmp(mode, "r")){ fd = open(pathname, O_RDONLY); }else if(!strcmp(mode, "w")){ fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, 0777); }else if(!strcmp(mode, "a")){ fd = open(pathname, O_WRONLY | O_CREAT | O_APPEND, 0777); }else{ return NULL; } if (fd < 0) return NULL; return mfdopen(fd, mode); } int mfclose(MFILE* fp) { mfflush(fp); //先刷新缓存 int ret = close(fp->_fd); free(fp->_buffer); free(fp); return ret; } void mfflush(MFILE* fp) { if(fp->_mode = READ){ fp->_nextc = fp->_buffer; fp->_left = 0; }else{ //WRITE or APPEND write(fp->_fd, fp->_buffer, (BUFFER_LEN - fp->_left)); fp->_nextc = fp->_buffer; fp->_left = BUFFER_LEN; } } MFILE* mfdopen(int fd, const char* const mode) { MFILE* fp = (MFILE*)malloc(sizeof(MFILE)); assert( fp != NULL); //断言fp存在 fp->_buffer = (char*)malloc(BUFFER_LEN); //创建缓冲区 assert(fp->_buffer != NULL); fp->_fd = fd; fp->_nextc = fp->_buffer; //初始化,指向缓冲区开始处 if(!strcmp(mode, "r")){ fp->_mode = READ; fp->_left = 0; //缓冲区剩余0字节未读取,即全部读完。 } if(!strcmp(mode, "w")){ fp->_mode = WRITE; fp->_left = BUFFER_LEN; //缓冲区剩BUFFER_LEN未写,即空的 } if(!strcmp(mode, "a")){ fp->_mode = APPEND; fp->_left = BUFFER_LEN; } return fp; } int mfgetc(MFILE* fp) { assert(fp->_mode == READ); //只允许读操作 //当缓存中的数据己读取完毕,先从文件中读取一批新的数据 //存入缓存中 if (fp->_left == 0){ ssize_t size = read(fp->_fd, fp->_buffer, BUFFER_LEN); assert( size >=0 ); if(size == 0) return MEOF; fp->_nextc = fp->_buffer; fp->_left = size; } char c = *(fp->_nextc); fp->_nextc++; fp->_left--; return c; } int mfputc(int character, MFILE* fp) { assert(fp->_mode == WRITE || fp->_mode == APPEND); //若缓存己满,则先将缓存中的数据写入到文件中 if(fp->_left == 0){ if(write(fp->_fd, fp->_buffer, BUFFER_LEN) != BUFFER_LEN){ return 0; } fp->_nextc = fp->_buffer; fp->_left = BUFFER_LEN; } *(fp->_nextc) = (char)character; fp->_nextc++; fp->_left--; return 1; //返回成功写入的字符个数 } int mungetc(int character, MFILE* fp) { int ret = 0; return ret; } char* mfgets(char* buff, int size, MFILE* fp) { char* ret = NULL; return ret; } int mfputs(char* buff, MFILE* fp) { int ret = 0; return ret; } size_t mfread(void* buff, size_t size, size_t counter, MFILE* fp) { size_t ret = 0; return ret; } size_t mfwrite(void* buff, size_t size, size_t counter, MFILE* fp) { size_t ret = 0; return ret; }
//mstdio_test.c
#include "mstdio.h" #include <stdio.h> #include <stdlib.h> #include <assert.h> int main(int argc, char* argv[]) { MFILE* fp1 = mfopen("/etc/passwd", "r"); assert(fp1 != NULL); MFILE* fp2 = mfopen("mypasswd", "w"); assert( fp2 != NULL); char c; while((c=mfgetc(fp1)) != MEOF){ mfputc(c, fp2); } mfclose(fp1); mfclose(fp2); return 0; }