实验七
Part 1:验证性实验
- 验证性实验2
将line 29做出修改后的源代码:
#include <stdio.h> #include <stdlib.h> #define N 10 typedef struct student { int num; char name[20]; int score; }STU; int main() { STU st, stmax, stmin; int i; FILE *fp; fp = fopen("file1.dat", "r"); if( !fp ) { printf("fail to open file1.dat\n"); exit(0); } stmax.score = 0; stmin.score = 100; while( !feof(fp) ) {//修改处,源代码为:for(i=0; i<N; i++) fscanf(fp, "%d %s %d", &st.num, st.name, &st.score); if(st.score > stmax.score) stmax = st; else if(st.score < stmin.score) stmin = st; } fclose(fp); printf("最高分学生信息: %5d%15s%5d\n", stmax.num, stmax.name, stmax.score); printf("最低分学生信息: %5d%15s%5d\n", stmin.num, stmin.name, stmin.score); return 0; }
运行结果:
显然,在不知道总人数的情况下,将line29的代码改为 while( !feof(fp) ) 之后,运行结果仍然正确。
这是因为,当fscanf()函数每运行完一行后。函数feof()判断下一行fscanf/fread函数返回值是否出错。若函数返回无错,则feof返回值为0。直到所有内容都被访问,fscanf/fread函数返回错误,feof()返回值为非0,循环结束。
- 对比验证性实验3和验证性实验4的程序源码及运行结果,总结比较二进制文件与文本文件的区别。
验证性实验3源代码:
#include <stdio.h> #include <stdlib.h> #define N 10 typedef struct student { int num; char name[20]; int score; }STU; void sort(STU *pst, int n); int main() { FILE *fin, *fout; STU st[N]; int i; fin = fopen("file1.dat", "r"); if( !fin ) { printf("fail to open file1.dat\n"); exit(0); } for(i=0; i<N; i++) fscanf(fin, "%d %s %d", &st[i].num, st[i].name, &st[i].score); fclose(fin); sort(st, N); fout = fopen("file3.dat", "w"); if( !fout ) { printf("fail to open file1.dat\n"); exit(0); } for(i=0; i<N; i++) { printf("%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score); fprintf(fout, "%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score); } fclose(fout); return 0; } void sort(STU *pst, int n) { STU *pi, *pj, t; for(pi = pst; pi < pst+n-1; pi++) for(pj = pi+1; pj < pst+n; pj++) if(pi->score < pj->score) { t = *pi; *pi = *pj; *pj = t; } }
运行结果:
验证性实验4代码:
#include <stdio.h> #include <stdlib.h> #define N 10 typedef struct student { int num; char name[20]; int score; }STU; void sort(STU *pst, int n); int main() { FILE *fin, *fout; STU st[N]; int i; fin = fopen("file1.dat", "r"); if( !fin ) { printf("fail to open file1.dat\n"); exit(0); } for(i=0; i<N; i++) fscanf(fin, "%d %s %d", &st[i].num, st[i].name, &st[i].score); fclose(fin); sort(st, N); fout = fopen("file3.dat", "wb"); if( !fout ) { printf("fail to open file1.dat\n"); exit(0); } for(i=0; i<N; i++) { printf("%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score); fprintf(fout, "%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score); } fclose(fout); return 0; } void sort(STU *pst, int n) { STU *pi, *pj, t; for(pi = pst; pi < pst+n-1; pi++) for(pj = pi+1; pj < pst+n; pj++) if(pi->score < pj->score) { t = *pi; *pi = *pj; *pj = t; } }
运行结果:
显然,验证性实验3中,file3是以“w”命令打开的,运行结果以文本文件的方式储存了起来,可以直接阅读;而实验4中,file4以“wb”命令打开,运行结果以二进制文件方式打开,需要专门的解码器才能查看。
p.s.由于在文本文件中,ASCII码每条数据(每个字符)都是1个字节长度固定,而二进制文件的数据是按类型划分,长度并不固定,导致两个数据文件的大小其实是不一样大的:
- 从二进制文件file4.dat中读出数据,并在屏幕上显示
源代码:
#include<stdio.h> #include<stdlib.h> typedef struct student { int num; char name[20]; int score; }STU;
int main() { FILE *fp; STU st[10]; int i=0,j; if((fp=fopen("file4.dat","rb"))==NULL){ printf("Failed to open file"); exit(0); } while(!feof(fp)){ if(fread(&st[i],sizeof(struct student),1,fp) == 1) { printf("%d\t%s\t%d\n", st[i].num, st[i].name, st[i].score); i++; } } fclose(fp); return 0; }
运行结果:
注意:feof判断文件结束是通过读取函数fread/fscanf等返回错误来识别的,故而判断文件是否结束应该是在读取函数之后进行判断。比如,在while循环读取一个文件时,如果是在读取函数之前进行判断,则如果文件最后一行是空白行,可能会造成内存错误。这也是为什么有些同学if后面的括号里没有“==1”程序运行会出错的原因。
Part 2:编程练习
源代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> const int N = 10; // 定义结构体类型struct student,并定义其别名为STU typedef struct student { long int id; char name[20]; float objective; /*客观题得分*/ float subjective; /*操作题得分*/ float sum; char level[10]; }STU; // 函数声明 void input(STU s[], int n); void output(STU s[], int n); void process(STU s[], int n); int main() { STU stu[N]; printf("录入%d个考生信息: 准考证号,姓名,客观题得分(<=40),操作题得分(<=60)\n", N); input(stu, N); printf("\n对考生信息进行处理: 计算总分,确定等级\n"); process(stu, N); printf("\n打印考生完整信息: 准考证号,姓名,客观题得分,操作题得分,总分,等级\n"); output(stu, N); return 0; } // 录入考生信息:准考证号,姓名,客观题得分,操作题得分 void input(STU s[], int n) { int i; FILE *fin; fin=fopen("examinee.txt","r");//只读方式打开"examinee.txt" if(fin==NULL){//若打开失败,则显示提示信息,然后退出程序 printf("fail to open examinee.txt\n"); exit(0); } for(i=0;i<n;i++){ fscanf(fin,"%d %s %f %f",&s[i].id,s[i].name,&s[i].objective,&s[i].subjective); }//从原文件读取数据 fclose(fin); } //输出考生完整信息: 准考证号,姓名,客观题得分,操作题得分,总分,等级 void output(STU s[], int n) { int i; FILE *fout; fout=fopen("result.txt","w");// 以只写文本方式打开/创建文件"result.txt" for(i=0;i<n;i++){ printf("%5d %10s %5.1f %5.1f %5.1f %10s\n",s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level);//在屏幕上输出结果 fprintf(fout,"%5d %10s %5.1f %5.1f %5.1f %10s\n",s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level);//在文件里输出结果 } fclose(fout); } void process(STU s[], int n) { int i,j,k,m=0; STU temp; for(i=0;i<n;i++) s[i].sum=s[i].objective+s[i].subjective; for(j=0;j<n;j++){ for(k=j;k<n;k++){ if(s[j].sum<s[k].sum){ temp=s[j]; s[j]=s[k]; s[k]=temp; } } }//对学生总分进行排序 while(m<=n){ if(m<=n*0.1-1) strcpy(s[m].level,"优秀); else if(m>n*0.1-1&&m<=n*0.5-1) strcpy(s[m].level,"合格); else strcpy(s[m].level,"不合格); m++; };//评定等级 }
运行结果:
Part 3:拓展综合应用
已知班级学生名单信息存在文本文件list.txt中,编程实现随机抽点任意位学生信息,显示在屏幕上,同时,写入文件
lucky.txt中。
源代码:
#include<stdio.h> #include<stdlib.h> #include<time.h> const int N=80; typedef struct student { int num; long int id; char name[20]; char cla[20]; }STU;//定义一个结构体变量 int main(){ STU rad[N]; int choose[80]; int i,j=0,judg=0,key,num; FILE *fin,*fout; fin=fopen("list.txt","r");// 以只读文本方式打开文件"list.txt" if(!fin){ printf("fail to open the file list.txt\n"); exit(0); }// 如果打开失败,则输出错误提示信息,然后退出程序 for(i=0;i<N;i++) fscanf(fin,"%d %ld %s %s",&rad[i].num,&rad[i].id,rad[i].name,rad[i].cla);//从文件中录入数据 printf("please input a number:"); scanf("%d",&num);//输入想要抽取的人数 srand(time(NULL));//设置随机数种子 fout=fopen("lucky.txt","w");// 以只写文本方式打开/创建文件lucky.txt fprintf(fout,"the inputed number is:%d\n\n",num); do{ key=rand()%80;//选取一个随机数 if(j) for(i=0;i<j;i++){ if(key==choose[i]) judg=1; } if(judg==1){ judg=0; continue; }//如果选中的随机数已经被选择过,便跳过此次循环 else{ printf("%d\t%ld\t%s\t%s\n",rad[key].num,rad[key].id,rad[key].name,rad[key].cla); fprintf(fout,"%d\t%ld\t%s\t%s\n",rad[key].num,rad[key].id,rad[key].name,rad[key].cla);//输出结果 choose[j++]=key;//将选中的随机数保存下来 } judg=0; }while(j<num); fclose(fin); fclose(fout); return 0; }
运行结果:
评论地址:
https://www.cnblogs.com/tedyoung1/p/11082228.html
https://www.cnblogs.com/hx-123/p/11079428.html
https://www.cnblogs.com/xu9729/p/11070705.html