一、作者想先说一点废话(狗头表情)
想必经常看我博客的小伙伴们已经发现我最近的博客风格和以往有些不同。以往的博客都是“一本正经不敢胡来”,但近段时间,文章风格却变得“废话连篇放荡不羁”,究竟是为什么呢(坏笑表情)?原来是作者在写博客的时候把自己和这段代码的故事给代入进去了,这样就让博客更生动有趣,在讲故事的同时让大家学习到算法思路,同时也可以学习到一些经验,在今后的学习中避免再走作者走过的弯路。
二、题目
已知一个数据文件a.txt中保存了若干个学生的计算机等级考试成绩,包括学号、姓名和成绩。请编程读出显示文件内容并分类统计各等级人数,最后显示统计结果。成绩等级规则:大于等于90-A,大于等于80-B,大于等于70-C,大于等于60-D,60以下-E。
二、最初算法思路
时代背景:拿到这个题目的时候,我数据结构正好学完单链表。
以往作风:我学完洛必达就觉得万物皆可洛必达,学完单链表就觉得万物皆可单链表。说白了就是思维定式,不会转弯。
一个我自认为完美的算法思路:
1、储存学生信息的结构体。
2、尾插法建立单链表,并读取文件中学生信息存在链表中。
3、将链表中的学生成绩转化为五级制成绩,统计并显示各等级人数。
于是有了如下代码:
#include#includetypedef struct students {//用于储存学生信息的结构体char id[20];//学号char name[20];//姓名char score[5];//成绩struct students* next;};void CreatList(students* list,FILE*pfile)//尾插法建立单链表,并读取文件中学生信息存在链表中{printf("文件中的学生信息为:\n");printf("学号\t姓名\t成绩\n");students* r = list;while (!feof(pfile))//若文件未结尾,则读取文件内容{students* p = (students*)malloc(sizeof(students));fscanf(pfile, "%s %s %s\n", &p->id, &p->name, &p->score);//读取学生信息并存放在链表中printf("%s\t%s\t%s\n", p->id, p->name, p->score);r->next = p;r = r->next;}r->next = NULL;}void grade(students* list){students* p = list->next;//p指向首元结点int A = 0, B = 0, C = 0, D = 0, E = 0;//定义各等级人数,并初始化为0while (p)//若p不为空,则进入循环{int x = atoi(p->score) / 10;//atoi用于将成绩转化为整型switch (x)//分级{case 10:case 9:A++;break;case 8:B++;break;case 7:C++;break;case 6:D++;break;case 5:case 4:case 3:case 2:case 1:case 0:E++;break;}p = p->next;//p向下移动一位}printf("A等级学生人数为:%d\n", A);printf("B等级学生人数为:%d\n", B);printf("C等级学生人数为:%d\n", C);printf("D等级学生人数为:%d\n", D);printf("E等级学生人数为:%d\n", E);}int main(){FILE* pfile;if ((pfile = fopen("a.txt", "r")) == NULL)//不要忘了pfile = fopen("a.txt", "r")外头的括号!{printf("不能打开文件!\n");exit(0);//相当于return 0;}students* list = (students*)malloc(sizeof(students));CreatList(list,pfile);//调用函数grade(list);//调用函数if (fclose(pfile))//程序结束用fclose关闭文件是一个良好的编程习惯{printf("不能正常关闭文件!\n");exit(0);}return 0;}
三、优化算法代码
过了一段时间,有个同学找我帮忙调试代码。
我一看:不就是这题吗?
再一看:代码长度给我震惊了,这段代码怎么比我的简单这么多!?
又一看:我怎么辣么傻,当初的算法真是愚蠢至极,用什么单链表!真没必要……
#include#includevoid grade(FILE* pfile){char id[20];//学号char name[20];//姓名char score[5];//成绩int A = 0, B = 0, C = 0, D = 0, E = 0;//定义各等级人数,并初始化为0while (!feof(pfile))//若文件未结尾{fscanf(pfile, "%s %s %s\n", &id, &name, &score);//读取学生信息int x = atoi(score) / 10;//atoi用于将成绩转化为整型switch (x)//分级{case 10:case 9:A++;break;case 8:B++;break;case 7:C++;break;case 6:D++;break;case 5:case 4:case 3:case 2:case 1:case 0:E++;break;}}printf("A等级学生人数为:%d\n", A);printf("B等级学生人数为:%d\n", B);printf("C等级学生人数为:%d\n", C);printf("D等级学生人数为:%d\n", D);printf("E等级学生人数为:%d\n", E);}int main(){FILE* pfile;if ((pfile = fopen("a.txt", "r")) == NULL)//不要忘了pfile = fopen("a.txt", "r")外头的括号!{printf("不能打开文件!\n");exit(0);//相当于return 0;}grade(pfile);//调用函数if (fclose(pfile))//程序结束用fclose关闭文件是一个良好的编程习惯{printf("不能正常关闭文件!\n");exit(0);}return 0;}