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 


一、思维导图

二、今日知识回顾

 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 <stdio.h>

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

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

(4)代码验证:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
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;
}

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 <stdio.h>

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

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

(4)代码验证:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
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;
}

2.1.3 无缓冲

(1)操作对象

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

(2)大小

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

(3)刷新条件:无

(4)代码验证

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
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;
}

三、课堂习题

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
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;
}

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

#include <stdio.h>
#include <head.h>
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;
}

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

#include <stdio.h>
#include <head.h>
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;
}

 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 <stdio.h>
#include <head.h>
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;
}

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

#include <stdio.h>
#include <head.h>
//用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;
}

 3.7 用fseek调整光标位置

#include <stdio.h>
#include <head.h>
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;
}

四、作业

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

#include <stdio.h>
#include <head.h>
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;
}

4.2 用fread和fwrite实现文件拷贝

方法一:

#include <stdio.h>
#include <head.h>
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 <stdio.h>
#include <head.h>
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;
}

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

/usr/include/head.h

#ifndef __HEAD_H__
#define __HEAD_H__

#include <string.h>
#include <unistd.h>

#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__); \
	perror(msg);\
}while(0);

#endif

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值