实验7(2019.6.18)
Part 1 【实验结论】
一、验证性实验。
1、验证性实验2。
Q:如果事先不知道学生人数,尝试对line29做如下修改后,程序运行结果是否正确?
for(i=0; i<N; i++) ↓↓↓ 改为 while( !feof(fp) )
验证结果如下:
|
修改前 for(i=0; i<N; i++)
|
修改后 while( !feof(fp) ) |
|
|
经验证,修改前后运行结果一致。
这段for循环和while(!feof(fp))条件本质上是一样的,都是在文件没有结束的前提下,在文件中提取信息。因而运行结果相同。
2、【总结】文本文件与二进制文件的区别。
(Ps:再次引用课外参考书的一段话,清晰明了)
(1)文本文件又称ASCⅡ文件,它的每一个字节存放一个ASCⅡ码,代表一个字符。
(2)二进制文件是把内存中的数据按其在内存中的存储形式原样输出到存储器上存放。
总之,用二进制形式输出数值,可节省外存空间和转换时间,但一个字节并不对应一个字符,不能直接输出字符格式,因而不能使用记事本软件打开。
3、编制一个小程序,从二进制文件file4.dat中读出数据,并在屏幕上显示。
代码如下:
1 //该程序功能:读取file4.dat的数据,输出到屏幕,并以文本文件方式保存在file4_1.txt中 2 #include<stdio.h> 3 #include<stdlib.h> 4 const int n=10; 5 typedef struct student { 6 int num; 7 char name[20]; 8 int score; 9 }STU; 10 int main(){ 11 int i; 12 STU st[n]; 13 FILE *hp; 14 hp=fopen("file4.dat","r"); 15 if(hp==NULL){ 16 printf("fail to open file4.dat\n"); 17 } 18 for(i=0;i<n;i++){ 19 fread(&st[i],sizeof(STU),n,hp); //使用块读写函数读取二进制文本中内容 20 } 21 fclose(hp); 22 FILE *fp; 23 fp=fopen("file4_1.txt","w"); 24 if(fp==NULL){ 25 printf("fail to open file4_1.txt\n"); 26 } 27 for(i=0;i<n;i++){ 28 printf("%d %s %d\n",st[i].num,st[i].name,st[i].score); 29 } 30 fwrite(st, sizeof(STU), n, fp); 31 fclose(fp); 32 return 0; 33 }
注:第19行,数据块读取函数fread可用于读取二进制数据块,不能使用scanf()函数,读出来的是乱码。(虽说我也不清楚为什么会这样,可能是因为格式化输入函数fscanf不能用于读取二进制数据?)
二、编程练习
此题可以习惯性地拆分任务:
•input部分,就是读取所给文件信息,使用fscanf函数。
•output部分,就是输出数据至屏幕以及输出数据到文本的操作,分别使用printf,fprintf函数
•process部分,这个和上次实验6的相似度极其高,你甚至可以ctrl+C与ctrl+V一下。(划掉)(手动滑稽)
于是就有了如下代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 const int N = 10; 5 6 // 定义结构体类型struct student,并定义其别名为STU 7 typedef struct student { 8 long int id; 9 char name[20]; 10 float objective; /*客观题得分*/ 11 float subjective; /*操作题得分*/ 12 float sum; 13 char level[10]; 14 }STU; 15 16 // 函数声明 17 void input(STU s[], int n); 18 void output(STU s[], int n); 19 void process(STU s[], int n); 20 21 int main() { 22 STU stu[N]; 23 24 printf("录入%d个考生信息: 准考证号,姓名,客观题得分(<=40),操作题得分(<=60)\n", N); 25 input(stu, N); 26 27 printf("\n对考生信息进行处理: 计算总分,确定等级\n"); 28 process(stu, N); 29 30 printf("\n打印考生完整信息: 准考证号,姓名,客观题得分,操作题得分,总分,等级\n"); 31 output(stu, N); 32 33 return 0; 34 } 35 36 // 从文本文件examinee.txt读入考生信息:准考证号,姓名,客观题得分,操作题得分 37 void input(STU s[], int n) { 38 // 补足代码 39 // ××× 40 FILE *fp; 41 int i; 42 fp=fopen("examinee.txt","r"); 43 if(!fp){ 44 printf("fail to open examinee.txt\n"); 45 exit(0); 46 } 47 for(i=0;i<n;i++){ 48 fscanf(fp,"%ld %s %f %f",&s[i].id,s[i].name,&s[i].objective,&s[i].subjective);//从文件中读取各种信息 49 } 50 fclose(fp); 51 } 52 53 // 输出考生完整信息: 准考证号,姓名,客观题得分,操作题得分,总分,等级 54 // 不仅输出到屏幕上,还写到文本文件result.txt中 55 void output(STU s[], int n) { 56 // 补足代码 57 // ××× 58 FILE *fpp; 59 int i; 60 fpp=fopen("result.txt","w"); 61 if(!fpp){ 62 printf("fail to open result.txt\n"); 63 exit(0); 64 } 65 for(i=0;i<n;i++){ 66 printf("%ld %s %lf %lf %lf %s\n",s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level);//输出至屏幕 67 fprintf(fpp,"%ld %s %lf %lf %lf %s\n",s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level);//输出至文件 68 } 69 fclose(fpp); 70 } 71 72 // 对考生信息进行处理:计算总分,排序,确定等级 73 void process(STU s[], int n) { 74 // 补足代码 75 // ××× 76 int i,j; 77 STU t; 78 //计算总分 79 for(i=0;i<n;i++){ 80 s[i].sum=s[i].objective+s[i].subjective; 81 } 82 //冒泡法排序 83 for(i=0;i<n;i++){ 84 for(j=0;j<n-1-i;j++){ 85 if(s[j].sum<s[j+1].sum){ 86 t=s[j]; 87 s[j]=s[j+1]; 88 s[j+1]=t; 89 } 90 } 91 } 92 //确定等级 93 strcpy(s[0].level,"优秀"); 94 for(i=1;i<=4;i++){ 95 strcpy(s[i].level,"合格"); 96 } 97 for(i=5;i<=9;i++){ 98 strcpy(s[i].level,"不合格"); 99 } 100 }
特别特别注意,第3行的#include <stdlib.h>,需要特别注意,如果你使用了如第45行的exit(0);函数,就要加上这个文件调用了。
运行结果如下:

“result.txt“中内容:

证明代码正确。
Part2 【实验总结与体会】
通过这次实验,能够帮助我们更好的理解、应用与文件有关的知识,复习了前几章的算法。
还有一个体会,就是要区分这么多读取/输出函数的用法,以及读取/写文本文件与二进制文件的区别。
快到期末了,还是得好好复习~,做一次实验能够顺便帮我们复习一些知识。
就这样吧。
谢谢大家的阅读、评论与支持!!!
-The end-
浙公网安备 33010602011771号