590 likes | 824 Views
项目 10 学生成绩单的保存与读取. 项目 10 学生成绩单的保存与读取. 【 学习目标 】. (1) 掌握 C 语言中文件的相关概念。 (2) 掌握文件有关操作常用标准库函数的使用。 (3) 掌握对文件的简单输入 / 输出操作。. 任务 10.1 将多个学生成绩单顺序读写到文件中. 任务介绍. 考试结束后,得到了全班学生多门课程的成绩。要求将一小组 3 个学生成绩信息写入到文件存档保存。学生成绩信息是个结构体,包括学生姓名、性别与学生成绩 3 个成员变量。 学生成绩信息如下: 肖飞 男 86 56 76 李雪 女 75 95 83
E N D
项目10 学生成绩单的保存与读取 【学习目标】 • (1) 掌握C语言中文件的相关概念。 • (2) 掌握文件有关操作常用标准库函数的使用。 • (3) 掌握对文件的简单输入/输出操作。
任务10.1 将多个学生成绩单顺序读写到文件中 任务介绍 考试结束后,得到了全班学生多门课程的成绩。要求将一小组3个学生成绩信息写入到文件存档保存。学生成绩信息是个结构体,包括学生姓名、性别与学生成绩3个成员变量。 学生成绩信息如下: 肖飞男86 56 76 李雪女75 95 83 郭键男91 89 61 要求输出格式为: 学生成绩信息为: 肖飞男86 56 76 李雪女75 95 83 郭键男91 89 61
任务10.1 将多个学生成绩单顺序读写到文件中 解决思路 方法: S1:初始化学生成绩信息到结构体数组。 S2:将结构体数组顺序写入到文件stuinfo.dat中。 S3:从stuinfo.dat中顺序读出学生信息,并输出。
任务10.1 将多个学生成绩单顺序读写到文件中 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: #define SIZE 3 struct student { char name[20]; char sex [3]; float score[SIZE]; }; struct student stu[SIZE]={{"肖飞","男",86,56,76},{"李雪","女",75,95,83}, {"郭键","男",91,89,61}}; void Save(struct student *pStu,char *fileName);
任务10.1 将多个学生成绩单顺序读写到文件中 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: void Read(char * fileName); void Output(struct student *pStu); void main() { char * fileName="stuInfo.dat"; Save(stu,fileName); Read(fileName); } void Output(struct student * pStu) { int i,j;
任务10.1 将多个学生成绩单顺序读写到文件中 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: for(i=0;i<SIZE;i++) { printf("%s\t%s\t",pStu->name,pStu->score); for( j=0;j<SIZE;j++) { printf("%3.0f\t",pStu->score[j]); } pStu++; printf("\n"); } } void Save(struct student *pStu,char *fileName)
任务10.1 将多个学生成绩单顺序读写到文件中 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: { FILE *fp; int i; if((fp=fopen(filename,"w"))==NULL) { printf("不能打开文件\n"); return; } for( i=0;i<SIZE;i++) { if(fwrite(pStu+i,sizeof(struct student),1,fp)!=1) {
任务10.1 将多个学生成绩单顺序读写到文件中 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: printf("文件写入错误\n"); break; } } fclose(fp); } void Read(char *fileName) { FILE *fp; int i; struct student stud[3];
任务10.1 将多个学生成绩单顺序读写到文件中 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: if((fp=fopen(filename,"r"))==NULL) { printf("不能打开文件\n"); return; } for(i=0;i<SIZE;i++) { fread(&stud[i],sizeof(struct student),1,fp); } fclose(fp); Output(stud); }
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.1 文件的基本概念 所谓“文件”,一般指存储在外部介质上数据的集合。 (1) ASCII文件。 (2) 二进制文件。
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.1 文件的基本概念
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.2 文件的打开与关闭 10.1.2.1 文件类型指针 定义一个文件类型的指针变量: (1) 语法。 FILE *指针变量名 例如: FILE *fp;
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.2 文件的打开与关闭 10.1.2.1 文件类型指针 定义一个文件类型的指针变量: (2) 语义。 fp是一个指向FILE类型结构体的指针变量。可以使fp指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息访问该文件。也就是说,通过文件指针变量能够找到与它相关的文件。通常,每个不同文件都应设不同的指针变量。 在对文件读写之前应该“打开”该文件,在文件使用介绍后应关闭该文件。
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.2 文件的打开与关闭 10.1.2.2 文件的打开 ANSI C规定了标准输入输出函数库,用fopen()函数来实现打开文件。 (1) 语法。 fp=fopen(文件名,使用文件方式) 例如: FILE * fp; fp=fopen("abc.txt","w");
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.2 文件的打开与关闭 10.1.2.2 文件的打开 ANSI C规定了标准输入输出函数库,用fopen()函数来实现打开文件。 (2) 语义。 表示要打开的名字为“abc.txt”的文件,使用方式为“写入”。fopen函数返回一个指向“abc.txt”文件的指针并赋给文件结构体指针fp,这样fp就指向了“abc.txt”文件。 在打开一个文件时,需要以下3个信息: 1) 需要打开的文件名,也就是准备访问的文件名字。 2) 使用文件的方式(“读”或“写”等)。 3) 让哪个指针变量指向被打开的文件。
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.2 文件的打开与关闭 10.1.2.2 文件的打开 表10-1 使用文件的方式
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.2 文件的打开与关闭 10.1.2.3 文件的关闭 用fclose函数关闭文件。 (1) 语法。 fclose(文件指针); 例如: fclose(文件指针);
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.2 文件的打开与关闭 10.1.2.3 文件的关闭 用fclose函数关闭文件。 (2) 语义。 在前面打开文件时,把打开文件所带回的指针赋值给了fp,通过fp把该文件关闭,即fp不再指向该文件。 应该养成在程序终止之前关闭所有文件的习惯,如果不关闭文件,将会丢失数据。因为如前所述,在向文件写数据时,是先将数据输到缓冲区,待缓冲区充满后才正式输出给文件。如果当数据未充满缓冲区而程序结束运行,就会将缓冲区中的数据丢失。用fclose函数关闭文件,可以避免这个问题,它先把缓冲区中的数据输出到磁盘文件,然后才释放文件指针变量。 fclose函数也返回一个值,如果返回值为0,则表示顺利执行了文件的关闭操作;否则返回EOF(-1)。
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.1 fputc 函数 (1) 语法。 fputc(字符常量/字符变量,文件指针); 例如: fputc(字符常量/字符变量,文件指针);
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.1 fputc 函数 (2) 语义。 将字符(ch的值)输出到fp所指向的文件中。fputc函数也返回一个值:如果输出成功,则返回值就是输出的字符;如果输出失败,则返回一个EOF(-1)。EOF是在stdio.h文件中定义的符号常量,值为-1。
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.2 fgetc 函数 (1) 语法。 字符变量=fgetc(fp) 例如: ch=fgetc(fp);
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.2 fgetc 函数 (2) 语义。 从fp所指向的文件中读取一个字符并赋给字符变量ch。如果在执行fgetc读字符时遇到文件结束符,函数返回一个文件结束标志EOF(-1)。
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 一个指针 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp); 要进行读写多少个size字节的数据项 要读写的字节数
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 【例10-2】从键盘上输入3个学生的信息,保存到文件“stu.dat”中,然后从文件中读取,并输出。 程序如下: #define SIZE 3 struct student { char name[10]; char sex [3]; int age; char address[20];
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 }; struct student stu[SIZE]; void Save(char *fileName); void Read(char *fileName); void Output(struct student *pStu); void main() { char *fileName="stu.dat"; int I;
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 printf("请输入三个学生的数据:姓名、性别、年龄与地址,数据用空格分隔\n"); for( i=0;i<SIZE;i++) { scanf("%s%s%d%s",&stu[i].name,&stu[i].sex,&stu[i].age,&stu[i].address); } Save(fileName); printf("学生数据已经保存\n"); printf("从文件中读出的学生数据为:\n");
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 Read(fileName); } void Output(struct student *pStu) { int i; for(i=0;i<SIZE;i++) { printf("%s\t%s\t%d\t%s\n",pStu->name,pStu->sex,pStu->age,pStu->address); pStu++; }
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 } void Save(char *fileName) { FILE *fp; int i; if((fp=fopen(filename,"w"))==NULL) { printf("不能打开文件\n"); return; } for(i=0;i<SIZE;i++)
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 { if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1) { printf("文件写入错误\n"); break; } } fclose(fp); } void Read(char *fileName) {
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 FILE *fp; int i; if((fp=fopen(filename,"r"))==NULL) { printf("不能打开文件\n"); return; } struct student stud[3]; for(i=0;i<SIZE;i++) { fread(&stud[i],sizeof(struct student),1,fp);
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.3 fread函数与fwrite函数 } fclose(fp); Output(stud); }
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.4 fprintf函数与fscanf函数
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.4 fprintf函数与fscanf函数 例如: fprintf(fp,"%d,%4.2f",i,j); 它的作用是将整型变量i和实型变量j的值按%d和%4.2f的格式输出到fp指向的文件上。 fscanf(fp,“%d,%f”,&i,&j); 它的作用是将文件中一个整型数据和一个实型数据读出,整型数据给变量i,实型数据给变量j。
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.4 fprintf函数与fscanf函数 【例10-3】格式化保存数据到文件中,并读出显示到屏幕上。 程序如下: void main() { char *fileName="file2.txt"; FILE *fp1,*fp2; int i; float j; if((fp1=fopen(filename,"w"))==NULL) { printf("打开文件错误\n");
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.4 fprintf函数与fscanf函数 exit(0); } printf("请输入一个整型数据与一个实型数据,数据之间用逗号隔开\n"); scanf("%d,%f",&i,&j); fprintf(fp1,"%d,%6.2f",i,j); fclose(fp1); printf("输入的数据已保存到文件file2.txt中\n"); printf("文件file2.txt中的内容为:\n"); if((fp2=fopen(filename,"r"))==NULL) {
任务10.1 将多个学生成绩单顺序读写到文件中 10.1.3 文件的顺序写入与读取 10.1.3.4 fprintf函数与fscanf函数 printf("打开文件错误\n"); exit(0); } int i2; float j2; fscanf(fp2,"%d,%f",&i2,&j2); fclose(fp2); printf("%d,%6.2f\n",i2,j2); }
任务10.2 更新文件中的学生成绩信息 任务介绍 任务10.1已经把学生的成绩信息保存到了文件“stuinfo.dat”中。现要求把学生李雪的第二门成绩由95更改为85,并保存。 学生成绩信息如下: 肖飞男86 56 76 李雪女75 95 83 郭键男91 89 61 要求输出格式为: 学生成绩信息为: 肖飞男86 56 76 李雪女75 95 83 郭键男91 89 61 更新后的学生成绩信息为: 肖飞男86 56 76 李雪女75 85 83 郭键男91 89 61
任务10.2 更新文件中的学生成绩信息 解决思路 方法1: S1:从文件中读出所有学生成绩信息到结构体数组中。 S2:把结构体数组中李雪的第二门课程的成绩由95改为85。 S3:把结构体数组重新全部写入到文件中。 通过方法1的描述,可以发现此方法存在效率低下的问题。假如文件中保存有几十条,上百条甚至几千条学生成绩记录的话,为了修改其中一条记录,而不得不对全部的记录进行读写,将会对程序的执行效率有很大的影响。
任务10.2 更新文件中的学生成绩信息 解决思路 由上述的分析可知,采用方式1实现本任务是不科学的。现介绍一种新的方法,只需对文件中“李雪”这条的记录进行读写操作,而不会涉及其他无关的记录。 方法2: S1:从文件中读出学生李雪一条成绩信息到结构体中。 S2:把结构体中李雪的第二门课程的成绩由95改为85。 S3:把结构体重新写入到文件中。
任务10.2 更新文件中的学生成绩信息 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: #define SIZE 3 struct student { char name[20]; char sex [3]; float score[SIZE]; }; void Read(char *fileName); void Output(struct student *pStu); void RandomRead(char *filename,int i); /*随机读函数*/ void RandomWrite(char *filename,struct student stud,int i);
任务10.2 更新文件中的学生成绩信息 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: void main() { char *fileName="stuInfo.dat"; printf("学生成绩信息为:\n"); Read(fileName); RandomRead(filename,1); printf("更新后的学生成绩信息为:\n"); Read(fileName); } void Output(struct student *pStu) { int I;
任务10.2 更新文件中的学生成绩信息 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: for(i=0;i<SIZE;i++) { printf("%s\t%s\t",pStu->name,pStu->sex); for(int j=0;j<SIZE;j++) printf("%3.0f\t",pStu->score[j]); } pStu++; printf("\n"); } } void Read(char *fileName) {
任务10.2 更新文件中的学生成绩信息 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: FILE *fp; int i; struct student stud[3]; if((fp=fopen(filename,"r"))==NULL) { printf("不能打开文件\n"); return; } for( i=0;i<SIZE;i++) { fread(&stud[i],sizeof(struct student),1,fp);
任务10.2 更新文件中的学生成绩信息 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: } fclose(fp); Output(stud); } void RandomRead(char *filename,int i) { FILE *fp; struct student stud; if((fp=fopen(filename,"r+"))==NULL) { printf("不能打开文件\n"); return;
任务10.2 更新文件中的学生成绩信息 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: } fseek(fp,i*sizeof(struct student),0); fread(&stud,sizeof(struct student),1,fp); fclose(fp); stud.score[1]=85.0f; RandomWrite(filename,stud,i); } void RandomWrite(char *fileName,struct student stud,int i) { FILE *fp; if((fp=fopen(filename,"r+"))==NULL) {
任务10.2 更新文件中的学生成绩信息 任务实现 根据上述的解决思路和相关知识点,具体程序实现如下: printf("不能打开文件\n"); return; } fseek(fp,i*sizeof(struct student),0); if(fwrite(&stud,sizeof(struct student),1,fp)!=1) { printf("文件写入错误\n"); fclose(fp); return; } fclose(fp); }
任务10.2 更新文件中的学生成绩信息 10.2.1 文件的定位 10.2.1.1 rewind函数 (1) 语法。 rewind(文件指针); 例如: rewind(fp); (2) 语义。 使位置指针重新返回文件的开头。函数没有返回值。
任务10.2 更新文件中的学生成绩信息 10.2.1 文件的定位 10.2.1.2 fseek函数 (1) 语法。 fseek(文件指针,位移量,起始点); 例如: fseek(fp,sizeof(struct student),0);
任务10.2 更新文件中的学生成绩信息 10.2.1 文件的定位 10.2.1.2 fseek函数 (2) 语义。 “起始点”用0,1或2代替,0代表“文件开始”;1为“当前位置”;2为“文件末尾”。 “位移量”指以“起始点”为基点,向前移动的字节数。ANSI C和大多数C版本要求位移量是long型数据。这样当文件的长度大于64 K时不致出问题。ANSI C标准规定在数字的末尾加一个字母L,就表示是long型。 用fseek函数可以实现改变文件的位置指针。