【实验结论】
Part1: 验证性实验
• 验证性实验二
将line29的代码做修改后的程序源码:
1 // 从文本文件file1.dat中读取数据,找出最高分和最低分学生信息,并输出在屏幕上 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 #define N 10 6 7 // 定义一个结构体类型STU 8 typedef struct student { 9 int num; 10 char name[20]; 11 int score; 12 }STU; 13 14 int main() { 15 STU st, stmax, stmin; 16 int i; 17 FILE *fp; 18 19 // 以只读文本方式打开文件file1.dat 20 fp = fopen("file1.dat", "r"); 21 if( !fp ) { // 如果打开失败,则输出错误提示信息,然后退出程序 22 printf("fail to open file1.dat\n"); 23 exit(0); 24 } 25 26 stmax.score = 0; // 先假定最高分是0,后面如发现比当前最高分还高的分数,就更新最高分 27 stmin.score = 100; // 先假定最低分是100分,后面如发现比当前最低分更低的分数,就更新最低分 28 29 while(!feof(fp)){ 30 fscanf(fp, "%d %s %d", &st.num, st.name, &st.score); // 从fp指定的文件中格式化读取一个学生信息 31 32 if(st.score > stmax.score) 33 stmax = st; 34 else if(st.score < stmin.score) 35 stmin = st; 36 } 37 38 fclose(fp); 39 40 printf("最高分学生信息: %5d%15s%5d\n", stmax.num, stmax.name, stmax.score); 41 printf("最低分学生信息: %5d%15s%5d\n", stmin.num, stmin.name, stmin.score); 42 43 return 0; 44 }
运行结果截图:
由运行结果可知,在不知道总人数的情况下,将line29的代码改为 while( !feof(fp) ) 之后,运行结果仍然是正确的。
这是因为,函数feof()是用于判断文件是否到了结束标志,函数的返回值若是非0的数,则说明文件指针已指向文件的结尾了。在这段代码中结构体变量st会一直从文件中读取数据,直到文件中的数据都已被访问。
• 对比验证性实验3和验证性实验4的程序源码及运行结果,总结比较二进制文件与文本文件的区别
? 验证性实验3:
程序源码:
1 // 从文本数据文件file1.dat中读入数据,按成绩从高到低排序,将排序结果输出到屏幕上,同时以文本方式存入文件file3.dat中。 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 #define N 10 6 7 // 定义一个结构体类型STU 8 typedef struct student { 9 int num; 10 char name[20]; 11 int score; 12 }STU; 13 14 void sort(STU *pst, int n); // 函数声明 15 16 int main() { 17 FILE *fin, *fout; 18 STU st[N]; 19 int i; 20 21 // 以只读文本方式打开文件file1.dat 22 fin = fopen("file1.dat", "r"); 23 if( !fin ) { // 如果打开失败,则输出错误提示信息,然后退出程序 24 printf("fail to open file1.dat\n"); 25 exit(0); 26 } 27 28 // 从fin指向的数据文件file1.dat中读取数据到结构体数组st 29 for(i=0; i<N; i++) 30 fscanf(fin, "%d %s %d", &st[i].num, st[i].name, &st[i].score); 31 32 fclose(fin); // 关闭fin指向的文件file1.dat 33 34 // 调用函数sort()对数组st中数据,按分数又高到低排序 35 sort(st, N); 36 37 // 以写方式打开/创建文本文件file3.dat 38 fout = fopen("file3.dat", "w"); 39 if( !fout ) { // 如果打开失败,则输出错误提示信息,然后退出程序 40 printf("fail to open file1.dat\n"); 41 exit(0); 42 } 43 44 // 将排序后的数组st中数据输出到屏幕,同时,也写入文件file3.dat 45 for(i=0; i<N; i++) { 46 printf("%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score); 47 fprintf(fout, "%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score); 48 } 49 50 fclose(fout); // 关闭fout指向的文件file3.dat 51 52 return 0; 53 }
运行结果截图:
? 验证性实验4:
程序源码:
1 // 从文本数据文件file1.dat中读入数据,按成绩从高到低排序,并将排序结果输出到屏幕上,同时,也以二进制方式存入文件file4.dat中。 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 #define N 10 6 7 // 定义一个结构体类型STU 8 typedef struct student { 9 int num; 10 char name[20]; 11 int score; 12 }STU; 13 14 void sort(STU *pst, int n); // 函数声明 15 16 int main() { 17 FILE *fin, *fout; 18 STU st[N]; 19 int i; 20 21 // 以只读文本方式打开文件file1.dat 22 fin = fopen("file1.dat", "r"); 23 if( !fin ) { // 如果打开失败,则输出错误提示信息,然后退出程序 24 printf("fail to open file1.dat\n"); 25 exit(0); 26 } 27 28 // 从fin指向的数据文件file1.dat中读取数据到结构体数组st 29 for(i=0; i<N; i++) 30 fscanf(fin, "%d %s %d", &st[i].num, st[i].name, &st[i].score); 31 32 fclose(fin); // 关闭fin指向的文件file1.dat 33 34 // 调用函数sort()对数组st中数据,按分数由高到低排序 35 sort(st, N); 36 37 // 以写方式打开/创建二进制文件file4.dat 38 fout = fopen("file4.dat", "wb"); 39 if( !fout ) { // 如果打开失败,则输出错误提示信息,然后退出程序 40 printf("fail to open file1.dat\n"); 41 exit(0); 42 } 43 44 // 将排序后的数组st中数据输出到屏幕 45 for(i=0; i<N; i++) 46 printf("%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score); 47 48 // 将排序后的数组st中数据写到二进制文件file4.dat 49 fwrite(st, sizeof(STU), N, fout); // 将从地址st开始的sizeof(STU)×N个字节信息写入fout指向的文件file4.dat中 50 51 fclose(fout); // 关闭fout指向的文件file4.dat 52 53 return 0; 54 } 55 56 57 // 函数功能描述:对pst指向的n个STU结构体数据进行排序,按成绩数据项由高到底排序 58 // 排序算法:冒泡法 59 void sort(STU *pst, int n) { 60 STU *pi, *pj, t; 61 62 for(pi = pst; pi < pst+n-1; pi++) 63 for(pj = pi+1; pj < pst+n; pj++) 64 if(pi->score < pj->score) { 65 t = *pi; 66 *pi = *pj; 67 *pj = t; 68 } 69 70 71 }
运行结果截图:
二进制文件与文本文件的区别总结:
|
数据类型 |
数据长度 |
读取软件 |
操作系统对换行符‘\n‘’的处理 |
文本文件 |
只能存储char型字符变量。 |
固定长度。如ASCII码每条数据(每个字符)都是1个字节 |
文本文件编辑器 |
操作系统会对‘\n‘进行一些隐式变换 |
二进制文件 |
可以存储char/int/short/long/float/等各种变量值。 |
不固定。如short占两个字节,int占四个字节,float占8个字节。 |
不同类型的需要特别解码器。 |
操作系统不会对‘\n‘进行隐式变换。 |
二进制文件file4.dat中读出数据:
程序源码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 typedef struct student { 4 int num; 5 char name[20]; 6 int score; 7 }STU; 8 int main() 9 { 10 FILE *fp; 11 STU st[10]; 12 int i=0,j; 13 if((fp=fopen("file4.dat","rb"))==NULL) 14 { 15 printf("Failed to open file"); 16 exit(0); 17 } 18 while(!feof(fp)) 19 { 20 fread(&st[i],sizeof(struct student),1,fp); 21 printf("%-6d %-10s %3d\n", st[i].num, st[i].name, st[i].score); 22 i++; 23 } 24 fclose(fp); 25 return 0; 26 }
运行结果截图:
这里运行结果的最后一行有什么意义?求解答!
程序源码:
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 // 录入考生信息:准考证号,姓名,客观题得分,操作题得分 37 void input(STU s[], int n) { 38 FILE *fin; 39 // 以只读文本方式打开文件examinee.txt 40 fin=fopen("examinee.txt","r"); 41 if( !fin ) { // 如果打开失败,则输出错误提示信息,然后退出程序 42 printf("Failed to open file\n"); 43 exit(0); 44 } 45 int i; 46 for(i=0;i<n;i++) 47 { 48 // 从fin指定的文件中格式化读取学生信息 49 if(fscanf(fin,"%ld %s %f %f",&s[i].id,s[i].name,&s[i].objective,&s[i].subjective)==0) 50 printf("读取错误!"); 51 } 52 fclose(fin); 53 } 54 55 //输出考生完整信息: 准考证号,姓名,客观题得分,操作题得分,总分,等级 56 void output(STU s[], int n) { 57 int i; 58 FILE *fout; 59 // 以只写文本方式打开/创建文件result.txt 60 fout=fopen("result.txt","w"); 61 //在屏幕和文档中打印表头 62 printf("准考证号 姓名 客观题得分 操作题得分 总分 等级\n"); 63 fprintf(fout,"准考证号 姓名 客观题得分 操作题得分 总分 等级\n"); 64 for(i=0;i<n;i++)// 格式化输出学生信息到fout指定的文件中 65 { 66 printf(" %-9ld%-10s%-13.2f%-10.2f%-7.2f%-8s\n", 67 s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level); 68 fprintf(fout," %-9ld %-10s%-13.2f%-10.2f%-7.2f%-8s\n", 69 s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level); 70 } 71 fclose(fout); 72 } 73 74 // 对考生信息进行处理:计算总分,排序,确定等级 75 void process(STU s[], int n) { 76 int i,j,k; 77 int a1,a2; //用来表示10%和50%两个分界点 78 a1=(int)(N*0.1),a2=(int)(N*0.5); 79 STU temp; 80 for(i=0;i<n;i++) 81 s[i].sum=s[i].objective+s[i].subjective; 82 for(j=0;j<n-1;j++) 83 for(k=0;k<n-j-1;k++) 84 if(s[k].sum<s[k+1].sum) 85 { 86 temp=s[k]; 87 s[k]=s[k+1]; 88 s[k+1]=temp; 89 } 90 for(i=0;i<a1;i++) 91 strcpy(s[i].level,"优秀"); 92 for(i=a1;i<a2;i++) 93 strcpy(s[i].level,"合格"); 94 for(i=a2;i<n;i++) 95 strcpy(s[i].level,"不合格"); 96 } 97
运行结果截图:
Part3: 拓展综合应用
程序源码:
1 #include<stdio.h> 2 #include<time.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #define N 80 6 typedef struct{ 7 int number; 8 char stu_number[10]; 9 char name[10]; 10 char class_name[20]; 11 int flag; //用于标志是否已被抽取到,防止重复抽取相同数据 12 }STU; 13 int main(){ 14 FILE *fin,*fout; 15 int i,j; 16 STU list[N]; 17 18 //数据读入 19 fin=fopen("list.txt","r"); 20 if(!fin){ 21 printf("Failed to open file"); 22 exit(0); 23 } 24 for(i=0;i<N;i++){ 25 fscanf(fin,"%d %s %s %s", &list[i].number, 26 list[i].stu_number, 27 list[i].name, 28 list[i].class_name); 29 list[i].flag=0; 30 } 31 fclose(fin); 32 33 //确定导出文件名 34 char buff[20]; 35 struct tm *t; 36 time_t tt; 37 time(&tt); 38 //调用 localtime函数查阅系统日期 39 t=localtime(&tt); 40 //调用 strftime函数将时间日期转换为字符串 41 if (!strftime(buff, sizeof buff, "%Y-%m-%d",t)) 42 //"%Y-%m-%d"这里有很多C99标准的代码无法使用 43 puts("strftime failed"); 44 strcat(buff,".txt"); //字符串连接函数--在字数串数组的结尾加上文件扩展名 45 46 //数据抽取、导出 47 srand(time(NULL)); 48 fout=fopen(buff,"w"); 49 if(!fout){ 50 printf("Failed to open file"); 51 exit(0); 52 } 53 i=0; 54 printf("Five lucky people:\n"); 55 while(i++<5){ 56 //生成随机数 57 j=rand()%N; 58 if(list[j].flag==0){ 59 fprintf(fout,"%02d %10s %-8s %-20s\n",list[j].number, 60 list[j].stu_number, 61 list[j].name, 62 list[j].class_name); 63 printf("%-2d %10s %-8s %-20s\n", list[j].number, 64 list[j].stu_number, 65 list[j].name, 66 list[j].class_name); 67 list[j].flag=1; //对已经抽到的成员进行标识 68 } 69 else{ 70 i--; 71 continue; 72 } 73 } 74 fclose(fout); 75 return 0; 76 }
运行结果截图:
【实验总结与体会】
待补充
原文:https://www.cnblogs.com/weiyuyang/p/11046961.html