第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 ...
随机推荐
- JavaScript权威指南——跳转语句
前言:JavaScript中有一类语句叫做跳转语句.从名称就可以看出,它使得JavaScript的执行可以从一个位置跳转到另一个位置. return语句让解释器跳出循环体的执行,并提供本次调用的返回值 ...
- Jordan标准形
一.引入 前面已经指出,一切n阶矩阵A可以分成许多相似类.今要在与A相似的全体矩阵中,找出一个较简单的矩阵来作为相似类的标准形.当然以对角矩阵作为标准形最好,可惜不是每一个矩阵都能与对角矩阵相似.因此 ...
- 【c++基础】如何获取工程项目当前路径
工程项目当前路径 #include <direct.h> int main( ) { ]; _getcwd(buffer, ); std::cout << buffer < ...
- LDA模型应用实践-希拉里邮件主题分类
#coding=utf8 import numpy as np import pandas as pd import re from gensim import corpora, models, si ...
- CF1142E/1143B Lynyrd Skynyrd
CF1142E/1143B Lynyrd Skynyrd 开始读错题了,以为是连续的一段,敲完后才发现是 \(subsequence\) ... 考虑对于 \(a\) 中的每个 \(a_i\) 找到它 ...
- (3)re模块(正则表达式模块)
什么是正则表达式 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 r ...
- 【CQOI2008】中位数
题不难,但是思路有意思,这个是我自己想出来的OvO 原题: 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. n<= ...
- day 2Linux软件从主机安装到服务器和安装JDK软件
软件安装 1.如何上传安装包到服务器**可以使用图形化工具,如: filezilla**可以使用sftp工具: alt+p 调出后,用put命令上传上传(如果不cd指定目录,则上传到当前用户的主目录) ...
- laravel5.3 源码分析 Passport
laravel5.3,密码模式的授权认证过程.我会通过两部分内容分享以及查看passport的认证流程分享出来 第一部分:根据官方文档,通过Composer安装Passport 文档地址:http:/ ...
- repo学习笔记
1. 遍历所有的git仓库,并在每个仓库执行-c所指定的命令(被执行的命令不限于git命令,而是任何被系统支持的命令,比如:ls . pwd .cp 等 . $ repo forall -c &quo ...