警院复试C程序设计学习笔记 第十章——对文件的输入输出

1.文件基本概念

2.

2.打开关闭及读写文件

接下来,我们通过代码实现对文件的读写:

自选目录新建两个.txt文件:

其中gushi.txt中有如下内容,而gushi2.txt是空的:

接下来,我们通过代码来实现将gushi.txt中的内容写入到gushi2.txt中。

代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(void){
	char name[100] = "D:\\Desktop\\c-learningnotes\\part10\\2.test\\gushi.txt";	//char name[50] = "D:/Desktop/c-learningnotes/part10/2.test/gushi.txt"等价
	FILE * fp = fopen(name, "r");
	if(fp == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}
	FILE * fp2 = fopen("D:\\Desktop\\c-learningnotes\\part10\\2.test\\gushi2.txt", "w");
	if(fp2 == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}
	char ch;
	while((ch = fgetc(fp)) != EOF)
		fputc(ch,fp2);
	fclose(fp);
	fclose(fp2);
	return 0;
}

执行结果如下:

打开gushi2.txt,发现文件内容被成功写入:

3.向文件读写一个字符串

这里涉及两个函数:fgets函数和fputs函数

自选目录新建一个txt文件,内容如下:

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main(void){
	char a[10];
	FILE * fp = fopen("D:\\Desktop\\c-learningnotes\\part10\\3.test\\78.txt", "r");
	if(fp == NULL){
		printf("打开文件失败,程序退出\n");
		exit(-1);
	}
	//把D:\\Desktop\\c-learningnotes\\part10\\3.test\\78.txt 读进来输出到屏幕上 
	fgets(a, 10, fp);	//程序第一次调用该句,a数组的内容为"123456\n",读到换行符时,fgets函数结束读入 
	fputs(a, stdout); 
	
	fgets(a, 10, fp);	//程序第二次调用该句,a数组的内容为"123456789",读到最大容纳的有效字符的个数9时,fgets函数结束读入 
	fputs(a, stdout);
	
	fgets(a, 10, fp);	//程序第三次调用该句,a数组的内容为"abcdefg" ,读到文件末尾时,fgets函数结束读入  
	fputs(a, stdout);
	putchar('\n');
	
	//把从键盘上输入的数据使用fgets和fputs输出到屏幕上 
	while(fgets(a, 10, stdin) != NULL)	//在windows系统下 在新的一行上(切记)按下ctrl+z+回车 就会输入文件结束标志EOF 
		fputs(a, stdout);
	fclose(fp);
	fp = NULL;	//最好使一个使用完的指针的值为NULL,这样可以避免野指针的出现 
	return 0;
}

执行结果如下:

4.用格式化的方式读写文件

要读的4.txt文件内容如下:

代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE * p1 = fopen("D:\\Desktop\\c-learningnotes\\part10\\4.test\\4.txt", "r");
	if(p1 == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}
	FILE * p2 = fopen("D:\\Desktop\\c-learningnotes\\part10\\4.test\\4-1.txt","w");
	if(p2 == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}
	int a;
	double b;
	char c[40];
	fscanf(p1, "%d%lf%s", &a, &b, c);
	fprintf(p2, "%d\n%.1lf\n%s\n", a, b, c);
	fclose(p1);
	fclose(p2);
	p1 = NULL;
	p2 = NULL;
	return 0;
}

执行结果如下:

文件4-1.txt中被写入内容:

5.用二进制的方式读写数据

代码如下:

#include <stdio.h>
#include <stdlib.h>
typedef struct{
	char name[30];
	double score;
}Stu;
int main(void){
	Stu a[3] = {{"zhangsan", 89.5},{"lisi", 78},{"wangwu", 90.1}};
	FILE * p1 = fopen("D:\\Desktop\\c-learningnotes\\part10\\5.test\\5.abc", "wb");
	if(p1 == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}  
	fwrite(a,sizeof(Stu), 3, p1);
	fclose(p1);
	p1 = fopen("D:\\Desktop\\c-learningnotes\\part10\\5.test\\5.abc","rb");
	if(p1 == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	} 
	Stu b[3];
	fread(b, sizeof(Stu), 3, p1);
	for(int i = 0; i < 3; ++i){
		printf("第%d个学生的姓名:%s,成绩:%.1lf\n", i+1, b[i].name, b[i].score );
	}
	fclose(p1);
	return 0;
}

执行结果如下:

6.文件读写的注意事项

通过代码来验证这句话:

要读取的文件内容如下:

代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE * p = fopen("D:\\Desktop\\c-learningnotes\\part10\\6.test\\6.txt", "rb");
	//打开方式为r时,输出3个ASCII码值,如果打开方式为rb,输出4个ASCII码值 
	if(p == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}
	char ch;
	while((ch = fgetc(p)) != EOF)
		printf("%d\n", ch);
	fclose(p);
	return 0;
}
/*
在windows系统下,使用fputc,fputs,fprintf向一个文件写入数据时,如果写入'\n',
文件的打开方式为文本模式,实际写入的是'\r'和'\n'两个字符;如果文件的打开方式
为二进制模式,实际就是写入一个'\n'字符。
使用fgetc,fgets,fscanf向一个文件读入数据时,如果读到'\r'和'\n',而且文件打
开方式为文本模式的时候,会把这两个字符当成一个'\n'读进来; 如果文件的打开方式
为二进制模式,那么不会发生这种转换,读进来的就是'\r'和'\n'两个字符

建议:如果文件本身是一个文本文件,就用文件模式的文件使用方式打开,对这个文件
进行读写就用这6个处理字符或者字符串的函数进行读写。 
*/

执行结果如下:

7.整型是如何存储在内存当中的

代码如下:

#include <stdio.h>
typedef union{
	int a;
	char b[4];
}A;
int main(void){
	A c;
	c.b[0] = 'A';
	c.b[1] = 'B';
	c.b[2] = 'C';
	c.b[3] = 'D';
	printf("%d\n", c.a ); //68×2^24+67×2^16+66×2^8+65=1145258561 整型数据在内存中是低位在前,高位在后的 
	return 0;
}

行结果如下:

8.文件读写注意事项2

代码如下:

#include <stdio.h>
#include <stdlib.h>
typedef struct{
	int a;
	int b;
}A;
int main(void){
	A c;
	fread(&c, sizeof(A), 1, stdin);		//stdin属于标准流文件的一种,凡是标准流文件的使用方式都是“文本模式”,所以这里就会发生字符转换 
	printf("%d, %d\n", c.a, c.b );
	return 0;
}
/*
输入1234按回车 
再输入1234按回车
输出: 
875770417, 858927370
a = 52*2^24+51*2^16+50*2^8+49
b = 51^2^24+50*2^16+49*2^8+10
建议:对二进制文件进行读写时用fread和fwrite函数,文本文件最好不要用这两个函数进行读写 
*/

执行结果如下:

9.rewind函数

下面我们通过代码示例来理解:

在指定目录下中,有一个9.txt文件,其中有如下内容:

而程序的功能是,让用户通过键盘把数据存放到指定目录下的指定文件末尾,最后再把这个稳健的所有内容输出到屏幕上。

代码如下:

//程序功能:让用户通过键盘把数据存放到指定目录下的指定文件末尾,最后再把这个稳健的所有内容输出到屏幕上 
#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE * p = fopen("D:\\Desktop\\c-learningnotes\\part10\\9.test\\9.txt","a+");
	if(p == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1); 
	}
	char ch;
	while((ch = getc(stdin)) != EOF){
		putc(ch ,p);
	}
	
	rewind(p);
	while((ch = getc(p)) != EOF){
		putc(ch, stdout);
	}
	fclose(p);
	return 0;
}

执行结果如下:

10.fseek函数

代码如下:

#include <stdio.h>
#include <stdlib.h>
typedef struct {
	char name[30];
	double score;
}A;

FILE * create(void);
void show(FILE * p);
int length(FILE * p);
bool insert(FILE * p, int index);
void sort(FILE * p);

int main(void){
	FILE * p = create();
//	insert(p,2);
	sort(p);
	show(p);
	fclose(p);
	return 0;
}

FILE * create(void){
	FILE * p = fopen("D:\\Desktop\\c-learningnotes\\part10\\10.test\\10.abc","wb+");
	if(p == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}
	int n;
	A b;
	printf("请输入学生数:\n");
	scanf("%d", &n);
	for(int i = 0; i < n; ++i){
		printf("请输入第%d个学生的姓名和成绩:\n", i+1);
		scanf("%s%lf", b.name, &b.score);
		fwrite(&b, sizeof(A), 1, p); 
	}
	return p;
}
void show(FILE * p){ 
	fseek(p, 0L, 0);	//	rewind(p); 与其等价
	A b;
	while(fread(&b, sizeof(A), 1, p) == 1)
		printf("学生姓名:%s,成绩:%lf\n", b.name, b.score); 
	
}
int length(FILE * p){
	fseek(p, 0L, 2);
	return ftell(p)/sizeof(A);
}
bool insert(FILE * p, int index){
	int len = length(p);
	if(index < 1 || index > len+1)
		return false;
	A b;
	for(int i = len-1; i >= index-1; --i){
		fseek(p, i*sizeof(A), 0);
		fread(&b, sizeof(A), 1, p);
		fseek(p, (i+1)*sizeof(A), 0);
		fwrite(&b, sizeof(A), 1, p);
	}
	printf("请输入所要插入的学生的姓名和成绩:\n");
	scanf("%s%lf", b.name, &b.score);
	fseek(p, (index-1)*sizeof(A), 0);
	fwrite(&b, sizeof(A), 1, p);
	return true;
}
void sort(FILE * p){
	int len = length(p);
	for(int i = 0; i < len-1; ++i){
		for(int j = 0; j < len-1-i; ++j){
			A b1, b2;
			fseek(p, j*sizeof(A), 0);
			fread(&b1, sizeof(A), 1, p);
			fread(&b2, sizeof(A), 1, p);
			if(b1.score > b2.score){
				fseek(p, j*sizeof(A), 0);
				fwrite(&b2, sizeof(A), 1, p);
				fwrite(&b1, sizeof(A), 1, p);
			}
		} 
	}
}

执行结果如下:

11.文件读写检测概念及错误应用

代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE * p = fopen("D:\\Desktop\\c-learningnotes\\part10\\11.test\\11.txt","r");	//该文件没有内容 
	if(p == NULL){
		printf("文件打开失败,程序退出\n");
		exit(0);
	}
	if(!feof(p))		//错误的使用feof判断文件有没有内容,文件结束和错误标志使用fopen函数后自动设置为0,所以这个时候使用feof或者ferror函数的返回值没有任何意义 
		printf("这个文件有内容\n");
	else
		printf("这个文件没有内容\n");
	printf("%d\n", ferror(p));	//输出0 
	fclose(p);
	return 0;
}

执行结果如下:

12.文件读写检测正确应用

在指定目录下,有一个12.txt,其内容为:

代码如下:

#include <stdio.h>
#include <stdlib.h>
void ce(FILE * p){			//建议大家,每当对文件进行I/O操作之后就要检测有没有读写错误,如果有就把错误这个错误清除 
	if(ferror(p)){
		printf("文件读写出错\n");
		clearerr(p);		
	}
}
int main(void){
	FILE * p = fopen("D:\\Desktop\\c-learningnotes\\part10\\12.test\\12.txt","r");
	if(p == NULL){
		printf("文件打开失败,程序退出\n");
		exit(0);
	}
	putc('A',p);
	ce(p);
	printf("%d\n", ferror(p));	//输出0,因为clearerr会把文件结束标志设置为0,即清除读写错误
	
	/* 
	char ch;
	while((ch = getc(p)) != EOF)	//getc函数会在读入出错或者读到文件末尾的时候返回EOF,所以如果文件产生读写错误,则很有可能不会把p所指向的稳健的全部内容读进来 
		putchar(ch);
	*/
	while(!feof(p)){				//此种做法可以把文件中的全部内容读进来输出到屏幕上,只不过末尾会多输出一个值为EOF的文件结束符 
		putchar(getc(p));
		ce(p); 	
	}
	printf("%d\n", feof(p));		//输出一个非0值,因为读写到达文件的末尾 
	clearerr(p);
	printf("%d\n", feof(p));		//输出0,因为clearerr会把文件的结束设置为0 
	fclose(p);
	return 0;
}

执行结果如下:

13.文件读写注意事项3

在指定目录下,有一个13.txt,其内容为:

代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(void){
	FILE * p = fopen("D:\\Desktop\\c-learningnotes\\part10\\13.test\\13.txt", "r+");
	if(p == NULL){
		printf("文件打开失败,程序退出\n");
		exit(-1);
	}
	putchar(getc(p));	//文件的读写是分时进行的,不能一会读一会写,反之也不可以。该语句使得文件标记处于读的状态,所以不能进行写的操作,可以使用rewind或者fseek函数解除文件标记的状态锁定,以便进行后面的读写 
//	rewind(p);			//可以把这两句去掉注释,然后对比88.txt的内容差别 
//	fseek(p, 1L, 0);
	putc('A', p);   
	fclose(p); 
}
//建议:尽量不要对一个文件既读又写,非常容易出错 

  • 16
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值