目录
一、思维导图
二、今日知识回顾
2.1 缓冲区
2.1.1 全缓冲
2.1.2 行缓冲
2.1.3 无缓冲
三、课堂习题
3.1 用fgets从文件中获取字符并打印到终端
3.2 用fgetc与fputc函数实现文件拷贝
3.3 用fgets计算一个文件有几个字符
3.4 fgets的选择题
3.5 用fwrite将结构体写进文件中
3.6 用fread将文件中的结构体读取到终端打印
3.7 用fseek调整光标位置
四、作业
4.1 使用fgets实现计算一个文件有几行
4.2 用fread和fwrite实现文件拷贝
4.3 封装自定义库函数head.h
1. 只有标准IO才有缓冲区,所有的数据都先放在缓冲区种,缓冲区满或者满足一定条件后刷新缓冲区。
2.在实际生活生产中,我们的代码会运行在死循环中,导致缓冲区可能不满且程序没有退出。所以必须掌握刷新缓冲区的条件。
(1)操作对象
(2)大小
//由于编译器优化,只打开不操作,此时不会真正申请缓冲区。
fputc('a', fp);
printf("%ld\n", fp->_IO_buf_end - fp->_IO_buf_base );
(3)刷新条件(6种):
#include
int fflush(FILE *stream);
功能:目前只要理解能退出程序即可;
原型:
#include
void exit(int status);
参数:
int status:目前随便填一个int类型整数即可,例如 1 2 0
(4)代码验证:
#include
#include
#include
int main(int argc, const char *argv[])
{
//以写的方式打开文件
FILE* fp = fopen("./fullBuf.txt","w");
if(NULL == fp)
{
perror("fopen");
return -1;
}
//输入单字符
fputc('a',fp);
fputc('b',fp);
fputc('c',fp);
printf("%ld\n",fp->_IO_buf_end - fp->_IO_buf_base);//打印全缓冲区的大小
fflush(fp);//刷新缓冲区
while(1)
{}
//关闭流指针
fclose(fp);
return 0;
}
(1)操作对象
(2)大小
printf("size=%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);
(3)刷新条件(7种):
#include
int fflush(FILE *stream);
功能:目前只要理解能退出程序即可;
原型:
#include
void exit(int status);
参数:
int status:目前随便填一个int类型整数即可,例如 1 2 0
(4)代码验证:
#include
#include
#include
int main(int argc, const char *argv[])
{
//stdin stdout stderr
char s1[20]="";
scanf("%s", s1);
printf("s1=%s\n", s1);
char s2[20]="";
fscanf(stdin,"%s", s2);
fprintf(stdout,"s2=%s\n", s2);
printf("stdin的size为%ld\n", stdin->_IO_buf_end - stdin->_IO_buf_base);
printf("stdout的size为%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);
printf("stderr的size为%ld\n", stderr->_IO_buf_end - stderr->_IO_buf_base);
return 0;
}
(1)操作对象
(2)大小
(3)刷新条件:无
(4)代码验证
#include
#include
#include
int main(int argc, const char *argv[])
{
/*
//查看无缓冲区的大小:
fputc('b',stderr);
printf("size=%ld\n", stderr->_IO_buf_end - stderr->_IO_buf_base);
*/
fputc('b',stderr);
perror("aaaaa");
return 0;
}
#include
#include
#include
int main(int argc, const char *argv[])
{
//打开文件,以读的方式
FILE* fp=fopen("./01_open.c","r");
if(NULL==fp)
{
perror("fopen");
return -1;
}
char s1[20]="";
while(1)
{
bzero(s1,sizeof(s1));
if(fgets(s1,sizeof(s1), fp)==NULL)
{
break;
}
printf("%s", s1);
}
return 0;
}
#include
#include
int main(int argc, const char *argv[])
{
//以读的形式打开文件1
FILE* fp_r=fopen("./02_fprintf.c","r");
if(NULL == fp_r)
{
ERR_MSG("fopen");
return -1;
}
//以写的形式打开文件2
FILE* fp_w=fopen("./2.txt","w");
if(NULL == fp_w)
{
ERR_MSG("fopen");
return -1;
}
//读一次写一次
char bf[128]="";
while(1)
{
bzero(bf,sizeof(bf));
if(fgets(bf,sizeof(bf),fp_r)==NULL)
break;
fputs(bf,fp_w);
}
printf("拷贝成功\n");
//关闭文件
if(fclose(fp_r)<0)
{
ERR_MSG("fclose");
return -1;
}
if(fclose(fp_w)<0)
{
ERR_MSG("fclose");
return -1;
}
return 0;
}
#include
#include
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./01_open.c","r");
if(NULL ==fp)
{
ERR_MSG("fopen");
return -1;
}
//循环读数
char str[2]="";
int count=0;
while(1)
{
if(fgets(str,sizeof(str),fp)==NULL)
break;
count+=strlen(str);
}
printf("count = %d\n",count);
if(fclose(fp)<0)
{
ERR_MSG("fclose");
}
return 0;
}
在文件中有如下数据:123456789 选(AD)
char str[9]; fgets(str, 10, fp); printf("str=%s", str);
A. 123456789 B.123456789乱码 C.12345678 D.段错误
#include
#include
typedef struct Car
{
char name[10];
int price;
}_C;
int main(int argc, const char *argv[])
{
FILE* fp=fopen("fwrite.txt","w");
if(NULL==fp)
{
ERR_MSG("fopen");
return -1;
}
_C car;
strcpy(car.name,"大众");
car.price=1000;
size_t res=0;
res = fwrite(&car,sizeof(_C),1,fp);
printf("size=%ld\n",res);
_C p[3]={"xjj",20,"xyt",20,"xjx",20};
res =fwrite(p,sizeof(_C),3,fp);
printf("size=%ld\n",res);
if(fclose(fp)<0)
{
ERR_MSG("fclose");
return -1;
}
return 0;
}
#include
#include
//用fread将文件中的结构体读取到终端打印
typedef struct Car
{
char name[10];
int price;
}_C;
int main(int argc, const char *argv[])
{
FILE* fp=fopen("fwrite.txt","r");
if(NULL==fp)
{
ERR_MSG("fopen");
return -1;
}
_C car;
size_t res=0;
while(1)
{
memset(&car,0,sizeof(car));
//一次读取一个_C类型的结构体数据,直到读完为止
res = fread(&car,sizeof(_C),1,fp);
if(0 == res)
break;
printf("res=%ld %s %d\n",res, car.name, car.price);
}
if(fclose(fp)<0)
{
ERR_MSG("fclose");
return -1;
}
return 0;
}
#include
#include
int main(int argc, const char *argv[])
{
//用fseek调整光标位置
FILE* fp=fopen("fseek.txt","w+");
if(NULL==fp)
{
ERR_MSG("fopen");
return -1;
}
fputc('A',fp);
fputc('B',fp);
fputc('C',fp);
int rec = fseek(fp,0,SEEK_SET);
printf("rec = %d\n",rec);
int c = 0;
rec = fseek(fp,-1,SEEK_SET);
printf("rec = %d\n",rec);
if(fclose(fp)<0)
{
ERR_MSG("fclose");
return -1;
}
return 0;
}
#include
#include
int main(int argc, const char *argv[])
{
//以读的方式打开文件
FILE* fp=fopen("./01_open.c","r");
if(NULL==fopen)
{
ERR_MSG("fopen");
return -1;
}
//循环读数
char str[2]="";
int count=0;
int line=0,i=0;
while(1)
{
//循环获取fp指针指向的文件中的数据,直至没有数据
if(fgets(str,sizeof(str),fp)==NULL)
break;
//计算个数
count+=strlen(str);
//计算行数
for(i=0;i<2;i++)
{
if(str[i]=='\n')
{
line++;
}
}
}
//打印个数、行数
printf("count = %d\nline = %d\n",count,line);
//关闭文件
if(fclose(fp)<0)
{
ERR_MSG("fclose");
return -1;
}
return 0;
}
方法一:
#include
#include
int main(int argc, const char *argv[])
{
//用fread和fwrite实现文件拷贝
//以读的方式打开文件1
FILE* fp_r=fopen("./01_open.c","r");
if(NULL == fp_r)
{
ERR_MSG("fopen");
return -1;
}
//以写的方式打开文件2
FILE* fp_w=fopen("./2.txt","w");
if(NULL == fp_w)
{
ERR_MSG("fopen");
return -1;
}
//循环读取文件1中的字符并写到文件2中,直至文件1字符结束
char a=0;
int rec=0;
while(1)
{
if(fread(&a,sizeof(a),1,fp_r)==0)
break;
fwrite(&a,sizeof(a),1,fp_w);
}
//关闭文件1
if(fclose(fp_r)<0)
{
ERR_MSG("fclose");
return -1;
}
//关闭文件2
if(fclose(fp_w)<0)
{
ERR_MSG("fclose");
return -1;
}
return 0;
}
方法二:
#include
#include
int main(int argc, const char *argv[])
{
FILE* fp_r = fopen("./02_fprintf.c","r");
if(NULL == fp_r)
{
ERR_MSG("fopen");
return -1;
}
FILE* fp_w = fopen("./2.txt","w");
if(NULL == fp_w)
{
ERR_MSG("fopen");
return -1;
}
char buf[128]= "";
size_t res=0;
while(1)
{
bzero(buf,sizeof(buf));
res=fread(buf, 1, sizeof(buf), fp_r);
if(0 == res)
break;
fwrite(buf, 1, res, fp_w);
}
printf("拷贝完毕\n");
fclose(fp_r);
fclose(fp_w);
return 0;
}
/usr/include/head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include
#include
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__); \
perror(msg);\
}while(0);
#endif