第3章 文件I/O(8)_贯穿案例:构建标准IO函数库
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, );
}else if(!strcmp(mode, "a")){
fd = open(pathname, O_WRONLY | O_CREAT | O_APPEND, );
}else{
return NULL;
} if (fd < ) 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 = ;
}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字节未读取,即全部读完。
} 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 == ){
ssize_t size = read(fp->_fd, fp->_buffer, BUFFER_LEN); assert( size >= ); if(size == ) 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 == ){
if(write(fp->_fd, fp->_buffer, BUFFER_LEN) != BUFFER_LEN){
return ;
} fp->_nextc = fp->_buffer;
fp->_left = BUFFER_LEN;
} *(fp->_nextc) = (char)character;
fp->_nextc++;
fp->_left--; return ; //返回成功写入的字符个数
} int mungetc(int character, MFILE* fp)
{
int ret = ; return ret;
} char* mfgets(char* buff, int size, MFILE* fp)
{
char* ret = NULL; return ret;
} int mfputs(char* buff, MFILE* fp)
{
int ret = ; return ret;
} size_t mfread(void* buff, size_t size, size_t counter, MFILE* fp)
{
size_t ret = ; return ret;
} size_t mfwrite(void* buff, size_t size, size_t counter, MFILE* fp)
{
size_t ret = ; 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 ;
}
第3章 文件I/O(8)_贯穿案例:构建标准IO函数库的更多相关文章
- 第8章 信号(6)_贯穿案例2:mini shell(3)
4. 贯穿案例2:mini shell(3) (1)之前存在问题 ①刚运行时,mshell作为前台进程.运行的其他命令会被加入新的进程组,并且调用tcsetpgrp将这个进程组设置为前台进程组,因此m ...
- 第7章 进程关系(5)_贯穿案例2:mini shell(2)
5. 贯穿案例2:mini shell(2) (1)己经完成的功能:pwd.cd.exit命令 (2)阶段性目标: ①env.export.echo及其他命令 ②标准输入.输出重定向"> ...
- Linux C 文件操作,系统调用 -- open()、read() 和 标准I/O库 -- fopen()、fread()
函数汇总: open().write().read().close() fopen().fwrite().fread().fclose() 一.什么是文件 在讲述文件操作之前,我们首先要知道什么是文件 ...
- 第4章 文件和目录(5)_贯穿案例2:mini shell(1)
6. 贯穿案例2:mini shell(1) [阶段性任务]实现cd.pwd和quit命令 //job.h #ifndef __JOB_H__ #define __JOB_H__ //接收命令行参数 ...
- 九、文件IO——案例构建标准库
例子如下: mystdio.h #ifndef __MYSTDIO_H__ #define __MYSTDIO_H__ #include <sys/types.h> #define MYE ...
- 【C语言入门教程】5.6 函数库和文件
函数库是为代码复用建立的,将同一类型,需要在不同的程序里使用的函数放置在一起,就组成了一个函数库.如 C 语言的标准库,它集合了开发者常用的函数.开发者自行编写的函数也可以组成函数库,通常称之为自定义 ...
- makefile笔记10 - makefile 函数库文件
函数库文件也就是对 Object 文件(程序编译的中间文件)的打包文件.在 Unix 下,一般是由命令"ar"来完成打包工作. 一.函数库文件的成员 一个函数库文件由多个文件组成. ...
- 循环 与 分支语句 和 字符函数库cctype 文件简单处理
循环 for循环 while循环 do while循环 通常,入口条件循环比出口条件循环好,因为循环开始前对条件进行检查 c++11基于范围的for循环 对数组(或容器类,如:vector和a ...
- 第3章 文件I/O(7)_高级文件操作:存储映射
8. 高级文件操作:存储映射 (1)概念: 存储映射是一个磁盘文件与存储空间的一个缓存相映射,对缓存数据的读写就相应的完成了文件的读写. (2)mmap和munmap函数 头文件 #include&l ...
随机推荐
- tp5中捕获异常的配置
首选在配置文件中加入配置如下 // 异常处理handle类 留空使用 \think\exception\Handle 'exception_handle' => '\\app\ ...
- Cookie注入实战(非SQL注入)
cookie注入原理其实很简单,就是利用了session机制中的特性,只能说是特性,不能算是漏洞. 这里简单的说下原理,session的机制就相当于你有一张蛋糕店的会员卡,这张会员卡就是你浏览器中的c ...
- Linux IO模式-阻塞io、非阻塞io、多路复用io
一 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进程的阻塞 - 文件描述符 - 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对3 ...
- 测试JS方法运行时间
console.time(label) 和 console.timeEnd(label), 在开始的地方写上 console.time("测试 fn 速度: ") ,在结束的地方写 ...
- DS博客作业04--树大作业说明
大作业题目说明 1.目录树 按照如下目录路径,设计一颗目录树保存.并能实现对目录树遍历.目录路径存在file.txt,格式如下: b.txt c\ ab\cd.txt a\bc.txt ab\d.tx ...
- Lua基本语法-书写规范以及自带常用函数
Lua基本语法-书写规范和常用函数 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 String Ope ...
- Oracle查询今天、昨天、本周、上周、本月、上月数据
查询今天数据: SELECT COUNT(1) FROM T_CALL_RECORDS WHERE TO_CHAR(T_RKSJ,'YYYY-MM-DD')=TO_CHAR(SYSDATE,'YYYY ...
- HDU 1872:稳定排序
稳定排序 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 斐波那契数列的5种python实现写法
斐波那契数列的5种python写法 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖 ...
- centos重启redis后,数据丢失
编辑/etc/sysctl.conf ,改vm.overcommit_memory=1, 然后sysctl -p 使配置文件生效 T