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函数库的更多相关文章

  1. 第8章 信号(6)_贯穿案例2:mini shell(3)

    4. 贯穿案例2:mini shell(3) (1)之前存在问题 ①刚运行时,mshell作为前台进程.运行的其他命令会被加入新的进程组,并且调用tcsetpgrp将这个进程组设置为前台进程组,因此m ...

  2. 第7章 进程关系(5)_贯穿案例2:mini shell(2)

    5. 贯穿案例2:mini shell(2) (1)己经完成的功能:pwd.cd.exit命令 (2)阶段性目标: ①env.export.echo及其他命令 ②标准输入.输出重定向"> ...

  3. Linux C 文件操作,系统调用 -- open()、read() 和 标准I/O库 -- fopen()、fread()

    函数汇总: open().write().read().close() fopen().fwrite().fread().fclose() 一.什么是文件 在讲述文件操作之前,我们首先要知道什么是文件 ...

  4. 第4章 文件和目录(5)_贯穿案例2:mini shell(1)

    6. 贯穿案例2:mini shell(1) [阶段性任务]实现cd.pwd和quit命令 //job.h #ifndef __JOB_H__ #define __JOB_H__ //接收命令行参数 ...

  5. 九、文件IO——案例构建标准库

    例子如下: mystdio.h #ifndef __MYSTDIO_H__ #define __MYSTDIO_H__ #include <sys/types.h> #define MYE ...

  6. 【C语言入门教程】5.6 函数库和文件

    函数库是为代码复用建立的,将同一类型,需要在不同的程序里使用的函数放置在一起,就组成了一个函数库.如 C 语言的标准库,它集合了开发者常用的函数.开发者自行编写的函数也可以组成函数库,通常称之为自定义 ...

  7. makefile笔记10 - makefile 函数库文件

    函数库文件也就是对 Object 文件(程序编译的中间文件)的打包文件.在 Unix 下,一般是由命令"ar"来完成打包工作. 一.函数库文件的成员 一个函数库文件由多个文件组成. ...

  8. 循环 与 分支语句 和 字符函数库cctype 文件简单处理

    循环 for循环 while循环 do  while循环 通常,入口条件循环比出口条件循环好,因为循环开始前对条件进行检查 c++11基于范围的for循环    对数组(或容器类,如:vector和a ...

  9. 第3章 文件I/O(7)_高级文件操作:存储映射

    8. 高级文件操作:存储映射 (1)概念: 存储映射是一个磁盘文件与存储空间的一个缓存相映射,对缓存数据的读写就相应的完成了文件的读写. (2)mmap和munmap函数 头文件 #include&l ...

随机推荐

  1. uDig配图与GeoServer添加Style

    软件介绍: uDig是一个开源的桌面GIS软件,可以进行shp与栅格数据地图文件的编辑和查看,对OpenGIS标准,关于互联网GIS.网络地图服务器和网络功能服务器有特别的加强.通常和GeoServe ...

  2. HDU 3488

    http://acm.hdu.edu.cn/showproblem.php?pid=3488 原来写过的一道题,今天重新看费用流又做了一遍 题意:给一个图,求环的并(权值和最小) 思路:每个点只能走一 ...

  3. AppStore 中的app怎么样生成二维码,来提供下载

    首先在:iTunes里面找到  AppStore模块,然后搜索你的 App 在App 下载选项有 Copy Link ,拷贝地址 在二维码生成器里直接生成二维码就,OK 如果,想要多个和安卓做一个二维 ...

  4. Java乱码解决之道

    1.常见字符编码 ASCII编码: ASCII,American Standard Code for Information Interchange,是基于拉丁字母的一套电脑编码系统,主要用于显示现代 ...

  5. BZOJ3473: 字符串【后缀数组+思维】

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  6. mysql安装错误解决办法

    在我们装mysql数据库时,出现安装失败是一件非常令人烦恼的事情,接下来小编就给大家带来在我们安装mysql数据库失败的一些解决方法,感兴趣的小伙伴们可以参考一下   mysql数据库安装不了了!my ...

  7. 自己一下午练习Js的代码

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Hive2:Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient

    [root@node1 ~]# hive which: no hbase in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bi ...

  9. PHP写的手机端网站,可以打包成app吗,怎么打包?

    8:13:36 沐歌-重庆 2018/1/19 8:13:36 PHP写的手机端网站,可以打包成app吗,怎么打包 风太大-淮安 2018/1/19 8:14:58 变色龙 沐歌-重庆 一般用什么打包 ...

  10. 【转】Ubuntu添加PATH环境变量

    原文网址:http://www.cnblogs.com/pang123hui/archive/2011/05/28/2309889.html 添加分两种: 一.临时性添加 ~$ echo $PATH  ...