0726|IO进程线程day2(标准IO函数2)

目录

一、思维导图

二、今日知识回顾

 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 


一、思维导图

0726|IO进程线程day2(标准IO函数2)_第1张图片

二、今日知识回顾

 2.1 缓冲区

1. 只有标准IO才有缓冲区,所有的数据都先放在缓冲区种,缓冲区满或者满足一定条件后刷新缓冲区。

2.在实际生活生产中,我们的代码会运行在死循环中,导致缓冲区可能不满且程序没有退出。所以必须掌握刷新缓冲区的条件。

2.1.1 全缓冲

(1)操作对象

  • 手动用fopen打开文件后,创建的缓冲区都是全缓冲。用FILE*类型流指针进行维护。

(2)大小

  • 4096bytes=4k
 //由于编译器优化,只打开不操作,此时不会真正申请缓冲区。
     fputc('a', fp);
     printf("%ld\n", fp->_IO_buf_end - fp->_IO_buf_base );

(3)刷新条件(6种):

  • 1> 缓冲区满 (要多写一个后才能刷新前4096个)
  • 2> fflush函数,强制刷新输出流缓冲区;
#include 

int fflush(FILE *stream);
  • 3> 关闭流指针 fclose
  • 4> 主函数调用return
  • 5> 调用exit函数退出程序
功能:目前只要理解能退出程序即可;
原型:
       #include 

       void exit(int status);
参数:
    int status:目前随便填一个int类型整数即可,例如 1 2 0
  • 6> 输入输出转换
  • 7> ...

(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;
}

0726|IO进程线程day2(标准IO函数2)_第2张图片

2.1.2 行缓冲

(1)操作对象

  • 标准输入流指针(FILE* stdin) 标准输出流指针(FILE* stdout)

(2)大小

  • 1024bytes = 1k
printf("size=%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);

(3)刷新条件(7种):

  • 1> 缓冲区满 (要多写一个后才能刷新前1024个)
  • 2> fflush函数,强制刷新输出流缓冲区;
#include 

int fflush(FILE *stream);
  • 3> 关闭流指针 fclose
  • 4> 主函数调用return
  • 5> 调用exit函数退出程序
功能:目前只要理解能退出程序即可;
原型:
       #include 

       void exit(int status);
参数:
    int status:目前随便填一个int类型整数即可,例如 1 2 0
  • 6> 遇到\n字符
  • 7> 输入输出转换

(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;
}

0726|IO进程线程day2(标准IO函数2)_第3张图片

2.1.3 无缓冲

(1)操作对象

  • 标准错误输出流指针(FILE* stderr) -->perror函数默认分装的就是stderr流指针。

(2)大小

  • 1bytes,且只要往里放数据,就会直接将数据刷新出来。

(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;
}

0726|IO进程线程day2(标准IO函数2)_第4张图片

三、课堂习题

3.1 用fgets从文件中获取字符并打印到终端

#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;
}

0726|IO进程线程day2(标准IO函数2)_第5张图片

3.2 用fgetc与fputc函数实现文件拷贝

#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;
}

0726|IO进程线程day2(标准IO函数2)_第6张图片

3.3 用fgets计算一个文件有几个字符

#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;
}

0726|IO进程线程day2(标准IO函数2)_第7张图片

 3.4 fgets的选择题

在文件中有如下数据:123456789  选(AD)

char str[9]; 
fgets(str, 10, fp);
printf("str=%s", str);

A. 123456789 B.123456789乱码 C.12345678 D.段错误

3.5 用fwrite将结构体写进文件中

#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;
}

0726|IO进程线程day2(标准IO函数2)_第8张图片

3.6  用fread将文件中的结构体读取到终端打印

#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;
}

0726|IO进程线程day2(标准IO函数2)_第9张图片

 3.7 用fseek调整光标位置

#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;
}

0726|IO进程线程day2(标准IO函数2)_第10张图片

四、作业

4.1 使用fgets实现计算一个文件有几行

#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;
}

0726|IO进程线程day2(标准IO函数2)_第11张图片

4.2 用fread和fwrite实现文件拷贝

方法一:

#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;
}

0726|IO进程线程day2(标准IO函数2)_第12张图片

方法二:

#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;
}

0726|IO进程线程day2(标准IO函数2)_第13张图片

4.3 封装自定义库函数head.h 

/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

0726|IO进程线程day2(标准IO函数2)_第14张图片

你可能感兴趣的:(IO进程线程,#,标准IO函数,linux,算法,运维)