应用IO编程——标准IO

1、标准IO编程——缓冲IO

1.1、概念

:所有的数据的输入或者输出仅是简单的从程序移进或者移出,这种字节流,就称为流。

流分类:文本流、二进制流

文件指针(FILE指针、即FILE结构体指针)

每个被使用的文件都在内存中开辟一个结构体空间,用来存放文件的有关信息,该结构体类型是由系统定义的,取名为FILE。

标准I/O库的所有操作都是围绕流(stream)来进行的,在标准I/O中,流用FILE *来描述。

标准I/O库是由Dennis Ritchie在1975年左右编写的。

//当执行一个程序时,会默认打开三个文件,分别是:标准输入,标准输出,标准错误输出 ,这三个文件会对应三个文件指针

			文件指针	文件描述符 
标准输入	  stdin		0  ---  STDIN_FILENO
标准输出	  stdout	1  ---  STDOUT_FILENO
标准错误输出   stderr	   2  ---  STDERR_FILENO

1.2、标准IO操作文件步骤

第一步:打开文件 ----- 获取文件指针

第二步:对文件进行读写操作

第三步:关闭文件

1.3、标准I/O - 带缓冲I/O

(带缓冲的目的:尽量减少使用read/write的调用)

在进行标准IO时,系统自动在内存中为每一个正在使用的文件开辟一个缓冲区,从内存向磁盘输出数据必须先送到内存缓冲区。

缓冲分三种情况:!!!

1.3.1、全缓存 -----常规文件

向文件中写数据或者从文件中读数据时,数据先保存到缓冲区中。

只有当缓冲区满或使用fflush()刷新或关闭文件时,才会将缓冲中的数据刷新到文件或程序中。

1.3.2行缓存 -----标准输入(键盘) 标准输出(屏幕)

向标准输出中写数据或者从标准输入中读数据时,数据先保存到缓冲区中。

只有当缓冲区中出现换行符’\n’ 或 使用fflush()刷新 或 关闭文件时时, 才会将缓冲中的数据刷新到标准输出或程序中。

1.3.3不缓存 -----标准错误输出(屏幕)

向标准错误输出写数据时,数据只要写到缓冲区中,就会立即被刷新。

int main(void)
{
	//fprintf(stdout,"hello world");  //通过标准输出打印数据:行缓冲----屏幕上看不到数据
	fprintf(stderr,"hello world");  //通过标准输出打印数据:无缓冲--屏幕上可以看到数据

	while(1);
	return 0;
}

1.4、标准IO打开文件的方法

FILE *fopen(const char *path, const char *mode);
//参数1:path  ------要打开的文件
//参数2:mode  ------打开的方式(操作权限)
	"r"		只读		文件必须存在
	"r+"	可读可写   文件必须存在,从文件开头开始覆盖文件原先的内容。
	"w"		只写		  文件可以不存在,如果不存在则创建,如果文件存在,则将文件清空
	"w+"	可读可写	 文件可以不存在,如果不存在则创建,如果文件存在,则将文件清空
	"a"		只写		  文件可以不存在,如果不存在则创建,如果文件存在,在文件末尾追加
	"a+"	可读可写	 文件可以不存在,如果不存在则创建,如果文件存在,在文件末尾追加
//返回值:成功返回FILE*,失败:NULL
        
例如:
int main(void)
{
	FILE * fp; 
	fp = fopen("1.txt","a");	//大家可以尝试使用不同的权限测试: r r+ w w+ a a+
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   
	return 0;
}      

1.5、标准IO关闭文件的方法

int fclose(FILE *fp);
//参数:fp -----FILE*类型的文件指针

例如: 
int main(void)
{
	FILE * fp; 

	//打开文件
	fp = fopen("1.txt","a");
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   
    
	//关闭文件
	fclose(fd);
	return 0;
}

1.6、格式化标准IO

数据在以字节流的形式传递过程中需要按照一定的格式传递。

1.6.1、格式化输入

int scanf(const char *format, ...);     //从键盘输入数据给程序
int fscanf(FILE *stream, const char *format, ...);   //从stream指向的文件中获取数据给程序
//例如: 
struct student{
	int sno;
	char name[20];
	float score;
};

int main(void)
{
	FILE * fp; 
	int n,i;

	printf("请输入学生的人数:");
	scanf("%d",&n);
	struct student st[n];
	
	//打开文件
	fp = fopen("1.txt","r+");
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   
	for(i = 0; i < n; i++)
		//fscanf(fp,"sno=%d,name=%s score=%f\n",&st[i].sno,st[i].name,&st[i].score);
		fscanf(fp,"%d%s%f\n",&st[i].sno,st[i].name,&st[i].score);
	
	for(i = 0; i < n; i++)
		printf("sno=%d  name=%s  score= %.2f\n",st[i].sno,st[i].name,st[i].score);	   
	return 0;
}
int sscanf(const char *str, const char *format, ...); 	//从str指向的内存中获取数据给程序
//例如: 
struct student{
	int sno;
	char name[20];
	float score;
};

int main(void)
{
	FILE * fp; 
	struct student st; 
	char buf[] = "1001 张三 98.56";
		
	sscanf(buf,"%d%s%f",&st.sno,st.name,&st.score);  //从buf中读取不同类型的数据
	printf("sno=%d,name=%s,score=%.2f\n",st.sno,st.name,st.score);
	return 0;
}

1.6.2、格式化输出

int printf(const char *format, ...);   					//向标准输出(屏幕)打印数据
int fprintf(FILE *stream, const char *format, ...);  	//向stream指向的文件中输出数据
//例如: 
struct student{
	int sno;
	char name[20];
	float score;
};

int main(void)
{
	FILE * fp; 
	int n,i;

	printf("请输入学生的人数:");
	scanf("%d",&n);
	struct student st[n];

	//打开文件
	fp = fopen("1.txt","a+"); //以追加方式打开文件
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   
	for(i = 0; i < n; i++){
		scanf("%d%s%f",&st[i].sno,st[i].name,&st[i].score);		//从键盘获取一条信息
		fprintf(fp,"%d\t%s\t%.2f\n",st[i].sno,st[i].name,st[i].score);   //向文件中写一条信息
	}   
	
	return 0;
}
int sprintf(char *str, const char *format, ...);		//向str指向的内存中写数据,有可能导致溢出
int snprintf(char *str, size_t size, const char *format, ...); //向str指向的内存中写size个字节数据,size表示内存空间的大小
//例如:
struct student{
	int sno;
	char name[20];
	float score;
};

int main(void)
{
	FILE * fp; 

	struct student st = {1001,"张三",98.56};
	char buf[100];
		
	sprintf(buf,"%d,%s,%.2f",st.sno,st.name,st.score);  //可以将不同类型的数据转换成一个字符串	
	printf("%s\n",buf);
	return 0;
}

1.7、非格式化标准IO

数据以字节流的形式在程序和文件之间传递。

1.7.1、一次读写一个字符的IO方法

一次读一个字符

int fgetc(FILE *stream);	//函数:从stream指向的文件中读一个字符
int getc(FILE *stream);		//宏:从stream指向的文件中读一个字符
int getchar(void);			//函数:从标准输入(键盘)读取一个字符
//函数的返回值:读到的字符的编码值
 //清空输入缓冲区!!!
while(getchar() != '\n');    
//例如: 
int main(int argc,char **argv)
{
	FILE * fp; 
	char ch; 
	//1,打开文件
	fp = fopen(argv[1],"r"); //以追加方式打开文件
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   
	//2,读取文件中的内容
	while((ch = fgetc(fp)) != EOF){
		printf("%c",ch);
	}   
	//关闭文件
	fclose(fp);
	return 0;
}

一次写一个字符

int fputc(int c, FILE *stream);    //函数:将字符c写入到stream指向的文件中
int putc(int c, FILE *stream);	 //宏:将字符c写入到stream指向的文件中
int putchar(int c);				//函数:将字符c写到标准输出(屏幕)
//向屏幕输出一个字符
putchar('A');    
//例如: 
int main(int argc,char **argv)
{
	FILE * fp; 
	char str[20];
	int i;

	//1,打开文件
	fp = fopen(argv[1],"w"); //以追加方式打开文件
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   

	//2,向文件中的写一个字符串
	printf("请输入一个字符串:");
	scanf("%s",str);
	for(i = 0; str[i] != '\0';i++)
		fputc(str[i],fp);

	//关闭文件
	fclose(fp);
	return 0;
}

1.7.2、一次读写一行的IO方法

一次读一行

char *fgets(char *s, int size, FILE *stream);  //从stream指向的文件中读一行数据保存到s指向的空间中
//参数1:s ----- 内存的地址
//参数2:size -- 内存空间大小
//参数3:stream--- 文件指针
//返回值:成功返回s,失败或者到文件末尾:NULL
//特别注意:
//fgets()函数在读取数据时,如果一行数据的长度大于size,则只接收size-1个字符,剩余的字符,会在下一次调用时读取,直到换行符'\n';如果一行数据的长度小于size,则读到换行符停止读取。
//当fgets()读取一个完整的行时,连同换行符一起读到s中。
        
char *gets(char *s);	//从标准输入获取一行数据保存到s指向的空间中,不会读取后面的换行符
//例如
int main(void)
{
	char buf[20];

	//fgets(buf,sizeof(buf),stdin);  //会接收换行符
	gets(buf);   //不会接收换行符
	printf("%s",buf);

	return 0;
}

int main(int argc,char **argv)
{
	FILE * fp; 
	char buf[100];
    
	//1,打开文件
	fp = fopen(argv[1],"r"); //以追加方式打开文件
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   

	//2,一次读一行
	while(fgets(buf,sizeof(buf),fp) != NULL){
		printf("%s",buf);
	}   

	//关闭文件
	fclose(fp);
	return 0;
}

一次写一行

int fputs(const char *s, FILE *stream);  //将s指向的字符串写入stream指向的文件中
//参数1:s ----- 内存的地址
//参数2:stream--- 文件指针
int puts(const char *s);   //将s指向的字符串打印到标准输出(屏幕)
//例如: 
int main(int argc,char **argv)
{
	FILE * fp; 
	char str[20];
	int i;

	//1,打开文件
	fp = fopen(argv[1],"w"); //以追加方式打开文件
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   

	//2,向文件中的写一个字符串
	printf("请输入一个字符串:");
	scanf("%s",str);
	fputs(str,fp);  //向文件中写一行数据

	//关闭文件
	fclose(fp);
	return 0;
}

1.7.3、一次读写一块的IO方法

一次读一块

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);  //从stream指向的文件中获取数据
//参数1:ptr ------存放数据的内存空间地址
//参数2:size -----对象的大小
//参数3:nmemb ----对象的个数
//参数4:stream ----文件指针 
//返回值:成功--读的对象的个数,失败:0
//例如: 
struct student{
	int sno;
	char name[20];
	float score;
};
int main(int argc,char **argv)
{
	FILE * fp; 
	int a[5],i;
	struct student st[3];

	//1,打开文件
	fp = fopen(argv[1],"r"); //以追加方式打开文件
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   

	//2,读取文件中的内容
#if 0
	fread(a,sizeof(int),5,fp);
	for(i = 0; i < 5; i++)
		printf("%d\t",a[i]);
	printf("\n");
#else
	fread(st,sizeof(struct student),2,fp);
	for(i = 0; i < 2; i++)
		printf("%d  %s  %.2f\n",st[i].sno,st[i].name,st[i].score);
#endif
	//关闭文件
	fclose(fp);
	return 0;
}

一次写一块

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);  //向stream指向的文件中写数据
//参数1:ptr ------存放数据的内存空间地址
//参数2:size -----对象的大小
//参数3:nmemb ----对象的个数
//参数4:stream ----文件指针 
//返回值:成功--读的对象的个数,失败:0
例如: 
struct student{
	int sno;
	char name[20];
	float score;
};

int main(int argc,char **argv)
{
	FILE * fp; 
	//int a[5] = {10,20,30,40,50};
	struct student st[] = {{1001,"Jack",98.45},{1002,"Rose",97.89}};
	int i;


	//1,打开文件
	fp = fopen(argv[1],"w"); //以追加方式打开文件
	if(NULL==fp){
		perror("fopen");
		exit(1);
	}   

	//2,向文件中的写对象
#if 0
	fwrite(a,sizeof(int),5,fp);  //写5个int型对象到文件中
#else
	fwrite(st,sizeof(struct student),2,fp);  //写5个int型对象到文件中
#endif
	//关闭文件
	fclose(fp);
	return 0;
}

1.8、总结

//标准IO中常用的函数
fopen()	fclose()
getchar() fgets() puts()
fread() fwrite()
对象对象\n
文件打开和关闭
fopenfclose
格式化
scanf从标准输入输入数据printf标准输出不读取,不补充
fscanf从文件获取数据fprintf文件不读取,不补充
sscanf从内存(读取不同类型的数据)sprintf内存
snprintf内存
非格式化
单个字符
fgetc文件fputc文件
getc文件putc文件读取,不补充
getchar(不是函数,而是宏)标准输入putchar(不是函数,而是宏)标准输出读取,不补充
fgets文件fputs文件读取,不补充
gets标准输入puts标准输出不读取,补充
freadfwrite
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值