C语言——基础的文件处理

ok,上期我们学完了链表,这期我们来学文件处理。其实你可能一直在接触文件处理,但是可能不知道到底什么是文件处理。比如说啊,你在HDUOJ提交了一份代码,那么OJ就会拿测试案例给你的代码运行对吧?那么,这些数据是怎么传入你的程序的呢?就是文件了。首先它会把准备好的测试案例放在一个文件里,然后让你的程序去读文件里的数据,再把你的输出存到一个文件里,和准备好的答案文件对比,如果完全一样,则accepted,也就是它觉得你的程序对了(如果测试点不完善的话可能程序还是错的)。

目录

文件处理应该做到什么?

1.打开文件

2.文件读写

        1>文本文件

        2>二进制文件

3.关闭文件

北航oj

1>

2>

3>

4>


文件处理应该做到什么?

思考一下,文件处理应该可以做到哪些功能?比如说打开文件;从文件中读取;输入数据到文件;还有关闭文件吧。这些就是最基础的文件处理操作了。

1.打开文件

        我们如果要使用一个文件的话,我们需要获得这个文件的地址,使用 fopen() 函数,就可以做到。我们开看看fopen的函数原型。

 首先,它的返回值是一个类型为 FILE*的指针,如果打开失败会返回一个NULL,所以应该判断是否打开成功其实FILE操作系统内部设置的用于保存文件的一种类型(这个我不是很懂,文件处理的时候可以把它当成一个文件就行。)我们需要创建一个指针去保存返回的地址。然后函数有两个参数,两个参数都是字符串类型的,第一个代表文件名称,第二个代表操作方式。首先讲文件名称

        文件名称:文件名称分两种,第一个是相对路径,相对路径是把文件操作再与源代码相同的文件目录下执行;第二种是绝对路径就是精确到某个盘,某个文件。一般提交oj只能用相对路径。

        操作方式:目前我学到的文件分两种,一种是txt文本文件,一种是dat二进制文件。一般只有text才是文本文件,其他的比如说mp3什么的,都是二进制文件。文本文件按ASCII保存字符,二进制文件按二进制保存字符和数字。当然,二进制文件的保密性比文本文件肯定高上不少。而且同一个二进制文件按照不同的解码方式可以有不同结果。所以,按照二进制进行文件处理的时候,必须特别注意格式。对文件的操作有读和写两种,分别对应 r 和 w ,再配上文件格式 文本为 t ,二进制为 b 。比如说下面这个

可以打开一个叫做result的文件,以 w (写)的形式打开,一个 b (二进制)文本。

r 打开只读文件,该文件必须存在。下面是基本的操作

  r+ 打开可读写的文件,该文件必须存在。

  rb+ 读写打开一个二进制文件,只允许读写数据。

  rt+ 读写打开一个文本文件,允许读和写。

  w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。

  w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。

  a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)

  a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 (原来的EOF符不保留)

  wb 只写打开或新建一个二进制文件;只允许写数据。

  wb+ 读写打开或建立一个二进制文件,允许读和写。

  wt+ 读写打开或着建立一个文本文件;允许读写。

  at+ 读写打开一个文本文件,允许读或在文本末追加数据。

2.文件读写

        1>文本文件

        实际上我们一直使用的 printf() ,scanf(),函授都是特殊的文件输出输入,只是输出和输入都是在控制台实现的,也不需要打开文件。向文本文件里输入就使用 fprintf()函数与printf()唯一的不同就是多了一个文件的地址作为参数。函数原型:

使用也和printf()基本一样。

读取文本文件里的数据,就使用fscanf()函数,和fprintf()类似,就不讲了。

        2>二进制文件

        前面说过对于二进制文件的读写有很严格的格式,所以函数也不能像fprintf()fscanf()一样了,需要使用 fwrite() fread()

 

 我们一看这两个函数就会发现,他们的参数是完全一样的。返回值是一个无符号的整型,其实就是读取/写入的元素个数。

Buffer -- 这是指向要被写入的元素数组的指针。
ElementSize -- 这是要被写入的每个元素的大小,以字节为单位。
ElementCount -- 这是元素的个数,每个元素的大小为 size 字节。
Stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。

如果返回值等于ElementCount则说明正常读取/写入。

    

                                    

 像这样一个结构体,我们要以二进制的形式写入文件的话,可以这么写。

读取也是一个道理。

3.关闭文件

        关闭文件,我们一般不判断是否成功了。(来自李卫明老师)。直接

                                                fclose(fp);

就行。

这里有几个北航的题目

北航oj

1>

题目描述

某班开设有英语、数学、程序设计三门课程,编写程序读入该班同学信息,排序后按总成绩保存在文本文件中result.txt。该班同学不多于50人。

输入描述

每行数据描述一个同学信息,包括名字、英语、数学、程序设计成绩

输出描述

该班同学总成绩排序,成绩相同时按输入次序。 每项占12位。

样例输入

张三    80 90 88 
李四    66 80 90
王五    50 78 87
Jack     68 86 70
Tom     60 88 96

样例输出

文本文件result.txt,内容格式如下
        Name    English     Math       C        Total
        张三          80          90          88         258
         Tom          60          88          96         244
        李四          66          80          90         236
        Jack          68          86          70         224
        王五          50          78          87         215
#include <stdio.h>
typedef struct {
	char name[20];
	int e;
	int m;
	int c;
	int total;
}students;
students stu[60];

int main()
{
	int i = 1;
	while (scanf("%s%d%d%d", stu[i].name,&stu[i].e,&stu[i].m,&stu[i].c)!=-1)
	{
		stu[i].total = stu[i].m + stu[i].e + stu[i].c;
		i++;
	}
	stu[i].total = stu[i].m + stu[i].e + stu[i].c;
	for (int j = 1; j <= i; j++)
	{
		for (int k = j + 1; k <= i; k++)
		{
			if (stu[j].total < stu[k].total)
			{
				students tem;
				tem = stu[j];
				stu[j] = stu[k];
				stu[k] = tem;
			}
		}
	}
	FILE* fp = fopen("result.txt", "wt");
	fprintf(fp, "         Name    English     Math       C        Total\n");
	for (int j = 1; j < i; j++)
	{
		fprintf(fp, "%12s%12d%12d%12d%12d\n", stu[j].name, stu[j].e, stu[j].m, stu[j].c, stu[j].total);
	}
	fclose(fp);
	return 0;
}

2>

题目描述

某班开设有英语、数学、程序设计三门课程,编写程序读入该班同学信息,按总成绩非递增排序后保存在二进制文件中result.dat中。该班同学不多于50人。

输入描述

每行数据描述一个同学信息,包括名字、英语、数学、程序设计成绩

输出描述

二进制文件result.dat,总成绩非递增排序后该班同学信息,总成绩相同时按输入次序排列,每位同学信息包含:名字(20字节字符数组),后4项,每项4字节整形,分别表示英语、数学、程序设计三门课程和总成绩。

样例输入

张三    80 90 88 
李四    66 80 90
王五    50 78 87
Jack     68 86 70
Tom     60 88 96

样例输出

二进制文件result.dat,由若干同学信息组成,每位同学信息包含:名字(20字节字符数组),后4项,每项4字节整形,分别表示英语、数学、程序设计三门课程和总成绩
#include <stdio.h>
typedef struct {
	char name[20];
	int e;
	int m;
	int c;
	int total;
}students;
students stu[60];

int main()
{
	int i = 1;
	while (scanf("%s%d%d%d", stu[i].name, &stu[i].e, &stu[i].m, &stu[i].c) != -1)
	{
		stu[i].total = stu[i].m + stu[i].e + stu[i].c;
		i++;
	}
	stu[i].total = stu[i].m + stu[i].e + stu[i].c;
	for (int j = 1; j <= i; j++)
	{
		for (int k = j + 1; k <= i; k++)
		{
			if (stu[j].total < stu[k].total)
			{
				students tem;
				tem = stu[j];
				stu[j] = stu[k];
				stu[k] = tem;
			}
		}
	}
	FILE* fp = fopen("result.dat", "wb");
	for (int j = 1; j <= i; j++)
	{
		fwrite(stu[j].name, sizeof(char), 20, fp);
		fwrite(&stu[j].e, sizeof(int), 1, fp);
		fwrite(&stu[j].m, sizeof(int), 1, fp);
		fwrite(&stu[j].c, sizeof(int), 1, fp);
		fwrite(&stu[j].total, sizeof(int),1, fp);
	}
	fclose(fp);
	return 0;
}

3>

题目描述

某班开设有英语、数学、程序设计三门课程,该班同学信息保存在文本文件student.txt中,编写程序从文件读入该班同学信息,再分别按总成绩和英语成绩排序。该班同学不多于50人。

输入描述

文本文件student.txt,每行数据描述一个同学信息,包括名字、英语、数学、程序设计成绩

输出描述

该班同学总成绩排序和英语成绩排序,题目保证成绩不相同。 每项占12位。

样例输入

文本文件student.txt,内容格式如下
张三    80 90 88 
李四    66 80 90
王五    50 78 87
Jack     68 86 70
Tom     60 88 96

样例输出

        Name    English     Math       C        Total
        张三          80          90          88         258
         Tom          60          88          96         244
        李四          66          80          90         236
        Jack          68          86          70         224
        王五          50          78          87         215


        Name    English     Math       C        Total
        张三          80          90          88         258
        Jack          68          86          70         224
        李四          66          80          90         236
         Tom          60          88          96         244
        王五          50          78          87         215
#include <stdio.h>
typedef struct {
	char name[20];
	int e;
	int m;
	int c;
	int total;
}students;
students stu[60];

int main()
{
	int i = 1;
	FILE* fp = fopen("student.txt", "rt");
	while (fscanf(fp,"%s%d%d%d", stu[i].name, &stu[i].e, &stu[i].m, &stu[i].c) != -1)
	{
		stu[i].total = stu[i].m + stu[i].e + stu[i].c;
		i++;
	}
	stu[i].total = stu[i].m + stu[i].e + stu[i].c;
	for (int j = 1; j <= i; j++)
	{
		for (int k = j + 1; k <= i; k++)
		{
			if (stu[j].total < stu[k].total)
			{
				students tem;
				tem = stu[j];
				stu[j] = stu[k];
				stu[k] = tem;
			}
		}
	}
	printf( "        Name    English     Math       C        Total\n");
	for (int j = 1; j < i; j++)
	{
		printf( "%12s%12d%12d%12d%12d\n", stu[j].name, stu[j].e, stu[j].m, stu[j].c, stu[j].total);
	}
	for (int j = 1; j <= i; j++)
	{
		for (int k = j + 1; k <= i; k++)
		{
			if (stu[j].e < stu[k].e)
			{
				students tem;
				tem = stu[j];
				stu[j] = stu[k];
				stu[k] = tem;
			}
		}
	}
	printf( "        Name    English     Math       C        Total\n");

	for (int j = 1; j < i; j++)
	{
		printf( "%12s%12d%12d%12d%12d\n", stu[j].name, stu[j].e, stu[j].m, stu[j].c, stu[j].total);
	}
	fclose(fp);
	return 0;
}

4>

题目描述

某班开设有英语、数学、程序设计三门课程,编写程序,从学生信息文件student.dat中读入该班同学信息,按英语成绩非递增排序后输出。该班同学不多于50人。

输入描述

二进制文件student.dat,包含该班同学信息,每位同学信息包含:名字(20字节字符数组),后4项,每项4字节整形,分别表示英语、数学、程序设计三门课程和总成绩。

输出描述

按英语成绩非递增排序后该班同学信息,英语成绩相同时按输入次序排列。

样例输入

二进制文件student.dat,由若干同学信息组成,每位同学信息包含:名字(20字节字符数组),后4项,每项4字节整形,分别表示英语、数学、程序设计三门课程和总成绩。

样例输出

        Name    English     Math       C        Total
        张三          80          90          88         258
        Jack          68          86          70         224
        李四          66          80          90         236
         Tom          60          88          96         244
        王五          50          78          87         215
#include <stdio.h>
typedef struct {
	char name[20];
	int e;
	int m;
	int c;
	int total;
}students;
students stu[60];

int main()
{
	int i = 1;
		char c;
	FILE* fp = fopen("student.dat", "rb");
	do {
		if (!fread(stu[i].name, sizeof(char), 20, fp))break;
		fread(&stu[i].e, sizeof(int), 1, fp);
		fread(&stu[i].m, sizeof(int), 1, fp);
		fread(&stu[i].c, sizeof(int), 1, fp);
		fread(&stu[i].total, sizeof(int), 1, fp);
		i++;
	} while (feof(fp)!=-1);
	stu[i].total = stu[i].m + stu[i].e + stu[i].c;
	for (int j = 1; j <= i; j++)
	{
		for (int k = j + 1; k <= i; k++)
		{
			if (stu[j].e < stu[k].e)
			{
				students tem;
				tem = stu[j];
				stu[j] = stu[k];
				stu[k] = tem;
			}
		}
	}
	printf("        Name    English     Math       C        Total\n");
	for (int j = 1; j < i; j++)
	{
		printf("%12s%12d%12d%12d%12d\n", stu[j].name, stu[j].e, stu[j].m, stu[j].c, stu[j].total);
	}

	fclose(fp);
	return 0;
}

真有人看到这的话,给个赞也不过分吧,哈哈。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值