目录
题目及要求:
录入学生成绩信息到链表中
合并文件
直接插入排序(总分降序)
冒泡排序(总分降序)
顺序查找(名字查找)
二分查找(名字查找)
这里是先按字母首字母排序再查找
保存不及格学生到文件中
题目及要求:
现有学生成绩信息文件 1(1.txt),内容如下(同学自己补充,共 30 名学生,数据文件格式与解析程序自己设定):
学生成绩信息文件 2(2.txt),内容如下(同上):
【实现要求】
试编写一管理系统,要求如下:
(1)实现对两个文件数据进行合并,生成新文件 3.txt
(2)抽取出三科成绩中有补考的学生(小于 60 分)并保存在一个新文件 4.txt
(3)对合并后的文件 3.txt 中的数据按总分降序排序(至少采用两种排序方法实现)
(4)输入一个学生姓名后,能查找到此学生的信息并输出结果(至少采用两种查找方法实现)
(5)要求使用结构体,链或数组等实现上述要求合并文件
录入学生成绩信息到链表中
List inputfile() {char stu[50];FILE *fp;List s,head,p;p=initlist();head=initlist();if((fp=fopen("E:\\3.txt","r"))==NULL) {printf("Could not open the file!");return 0;}fgets(stu,50,fp);head=p;while(!feof(fp)) { //尾插法s=initlist();//文件刚开始不能读入第一行元素,原因是文件空行的问题fscanf(fp,"%s%d%d%d%d\n",s->std.name,&s->std.stdID,&s->std.Chinese,&s->std.Math,&s->std.Engish);s->std.total=s->std.Chinese+s->std.Engish+s->std.Math;p->next=s;p=s;}p->next=NULL;fclose(fp);return head;}
合并文件
int combination() {FILE *fp1=fopen("E:\\1.txt","rb+"); //读入文件1.txtFILE *fp2=fopen("E:\\2.txt","rb+"); //读入文件2.txtFILE *fp3=fopen("E:\\3.txt","wb+"); //写入文件3.txtchar c;if(fp1==NULL||fp2==NULL||fp3==NULL) {puts("Could not open the files\n");return 0;}while((c=fgetc(fp1))!=EOF) //读到文件末尾返回EOF(-1)fputc(c,fp3); //逐个字符写入文件3.txtwhile((c=fgetc(fp2))!=EOF)fputc(c,fp3);printf("Merged 1.txt and 2.txt into 3.txt\n");fclose(fp1);fclose(fp2);fclose(fp3);return 1;}
直接插入排序(总分降序)
List sortscore1() {List p,q,head,r;head=inputfile();p=head->next; //带头结点和第一个元素的链表q=p->next;//第一个元素后面的链表p->next=NULL; //链表一后面为空while(q!=NULL) {//连表二不为空执行p=head; //头结点,p表示头结点,在下面一定不要搞混r=q->next; //链表二第一个元素的下一个while(p->next!=NULL) { //头结点下一个不为空时执行if(p->next->std.total>q->std.total) { //p->next表示头结点的下一个元素对应的总分,大于不需要调整,继续比下一个p=p->next;} else {break;}}q->next=p->next; //当链表一p的第一个小于链表二q的第一个元素,将q的第一个元素头插到p中p->next=q; //插入q的第一个元素在p头结点后q=r;//移动q到r}return head;}
冒泡排序(总分降序)
List sortscore2() {List p,q,head,tail;tail=NULL;head=inputfile();while((head->next->next!=tail)) {p=head;q=head->next;while(q->next!=tail) {if((q->std.total)<(q->next->std.total)) { //小于调换p->next=q->next;q->next=q->next->next;p->next->next=q;q=p->next;}q=q->next;p=p->next;}tail=q;}return head;}
顺序查找(名字查找)
void search_Name1() {List p=sortscore1(); //循环使用函数,要在前面声明函数,否则出现conflicting types for"XXX"char a[10];printf("请输入查找的名字:");scanf("%s",a);while(p) {if(0==strcmp(a,p->std.name)) {//字符串匹配strcmp()printf("姓名\t学号\t语文\t数学\t英语\t总分\n");printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish,p->std.total);break;}p=p->next;if(p==NULL)printf("Could not find!\n");//找不到返回}}
二分查找(名字查找)
这里是先按字母首字母排序再查找
void search_Name2() {FILE *fp;Studentdata temp;Studentdata stu[60]; //要加static,否则后面会出现报错,改变了局部变量memset(stu,0,sizeof(stu)); //初始化数组int i=0,n,m;char std[50];if((fp=fopen("E:\\3.txt","rb+"))==NULL) {printf("Could not open the file!");exit(0);}fgets(std,50,fp);while(!feof(fp)) {fscanf(fp,"%s%d%d%d%d",stu[i].name,&stu[i].stdID,&stu[i].Chinese,&stu[i].Math,&stu[i].Engish); //数组存数据stu[i].total=stu[i].Chinese+stu[i].Math+stu[i].Engish;i++;}fclose(fp);for(n=0; n<i-1; n++) {for(m=0; m<i-n; m++) {if(strcmp(stu[m].name,stu[m+1].name)>0) {//按姓名字母排序temp=stu[m];stu[m]=stu[m+1];stu[m+1]=temp;}}}printf("%d",i);for(n=0; n<i; n++) {printf("%s %.2d %d %d %d %d\n",stu[n].name,stu[n].stdID,stu[n].Chinese,stu[n].Math,stu[n].Engish,stu[n].total);}char a[10];printf("请输入查找的名字:");scanf("%s",a);int low=1,high=i,mid;while(low<high) {mid=(low+high)/2;if(strcmp(a,stu[mid].name)==0) {printf("姓名\t学号\t语文\t数学\t英语\t总分\n");printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",stu[mid].name,stu[mid].stdID,stu[mid].Chinese,stu[mid].Math,stu[mid].Engish,stu[mid].total);break;} else if(strcmp(stu[mid].name,a)<0)low=mid+1;else high=mid-1;if(low==high)printf("Could not find!\n");//找不到返回}}
保存不及格学生到文件中
int bujige() {int key=60;List p=inputfile()->next;FILE *fp1=fopen("E:\\3.txt","rb+");FILE *fp2=fopen("E:\\4.txt","wb+");if((fp1==NULL)||(fp2==NULL)) {printf("Could not open the file!");return 0;}while(p) {if((p->std.Chinese<key)||(p->std.Engish<key)||(p->std.Math<key)) {fprintf(fp2,"%s %.2d %d %d %d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish);}p=p->next;}printf("4.txt successfully saved!\n");fclose(fp1);fclose(fp2);}
完整代码
#include<stdio.h>#include<locale.h>#include<stddef.h>#include<stdlib.h>#include<string.h>typedef struct {int stdID;int Chinese;int Math;int Engish;int total;char name[10];} Studentdata,*ST;typedef struct student {Studentdata std;struct student *next;} student,*List;List initlist() { //初始化头结点List head;head=(List)malloc(sizeof(student));head->next=NULL;return head;}//函数声明,不声明,下面调用函数会出现错误int combination(); //合并函数 ,合并1.txt和2.txt到3.txt中List inputfile(); //录入成绩int bujige(); //补考学生保存4.txtList sortscore1();//排序List sortscore2();//排序void search_Name1();//查找void search_Name2();//名字排序并查找//读入学生的信息List inputfile() {char stu[50];FILE *fp;List s,head,p;p=initlist();head=initlist();if((fp=fopen("E:\\3.txt","r"))==NULL) {printf("Could not open the file!");return 0;}fgets(stu,50,fp);head=p;while(!feof(fp)) { //尾插法s=initlist(); //文件刚开始不能读入第一行元素,原因是文件空行的问题fscanf(fp,"%s%d%d%d%d\n",s->std.name,&s->std.stdID,&s->std.Chinese,&s->std.Math,&s->std.Engish);s->std.total=s->std.Chinese+s->std.Engish+s->std.Math;p->next=s;p=s;}p->next=NULL;fclose(fp);return head;}//查找不及格的保存文件4.txt中int bujige() {int key=60;List p=inputfile()->next;FILE *fp1=fopen("E:\\3.txt","rb+");FILE *fp2=fopen("E:\\4.txt","wb+");if((fp1==NULL)||(fp2==NULL)) {printf("Could not open the file!");return 0;}while(p) {if((p->std.Chinese<key)||(p->std.Engish<key)||(p->std.Math<key)) {fprintf(fp2,"%s %.2d %d %d %d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish);}p=p->next;}printf("4.txt successfully saved!\n");fclose(fp1);fclose(fp2);}//合并后的学生成绩按总分降序排序,两种排序方法实现//直接插入排序,拆分链表List sortscore1() {List p,q,head,r;head=inputfile();p=head->next; //带头结点和第一个元素的链表q=p->next;//第一个元素后面的链表p->next=NULL; //链表一后面为空while(q!=NULL) {//连表二不为空执行p=head; //头结点,p表示头结点,在下面一定不要搞混r=q->next; //链表二第一个元素的下一个while(p->next!=NULL) { //头结点下一个不为空时执行if(p->next->std.total>q->std.total) { //p->next表示头结点的下一个元素对应的总分,大于不需要调整,继续比下一个p=p->next;} else {break;}}q->next=p->next; //当链表一p的第一个小于链表二q的第一个元素,将q的第一个元素头插到p中p->next=q; //插入q的第一个元素在p头结点后q=r;//移动q到r}return head;}//冒泡排序List sortscore2() {List p,q,head,tail;tail=NULL;head=inputfile();while((head->next->next!=tail)) {p=head;q=head->next;while(q->next!=tail) {if((q->std.total)<(q->next->std.total)) { //小于调换p->next=q->next;q->next=q->next->next;p->next->next=q;q=p->next;}q=q->next;p=p->next;}tail=q;}return head;}//查找学生的信息并输出结果//顺序查找void search_Name1() {List p=sortscore1(); //循环使用函数,要在前面声明函数,否则出现conflicting types for"XXX"char a[10];printf("请输入查找的名字:");scanf("%s",a);while(p) {if(0==strcmp(a,p->std.name)) {//字符串匹配strcmp()printf("姓名\t学号\t语文\t数学\t英语\t总分\n");printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish,p->std.total);break;}p=p->next;if(p==NULL)printf("Could not find!\n");//找不到返回}}//按姓氏字母排序并查找,二分查找void search_Name2() {FILE *fp;Studentdata temp;Studentdata stu[60]; //要加static,否则后面会出现报错,改变了局部变量memset(stu,0,sizeof(stu)); //初始化数组int i=0,n,m;char std[50];if((fp=fopen("E:\\3.txt","rb+"))==NULL) {printf("Could not open the file!");exit(0);}fgets(std,50,fp);while(!feof(fp)) {fscanf(fp,"%s%d%d%d%d",stu[i].name,&stu[i].stdID,&stu[i].Chinese,&stu[i].Math,&stu[i].Engish); //数组存数据stu[i].total=stu[i].Chinese+stu[i].Math+stu[i].Engish;i++;}fclose(fp);for(n=0; n<i-1; n++) {for(m=0; m<i-n; m++) {if(strcmp(stu[m].name,stu[m+1].name)>0) {//按姓名字母排序temp=stu[m];stu[m]=stu[m+1];stu[m+1]=temp;}}}printf("%d",i);for(n=0; n<i; n++) {printf("%s %.2d %d %d %d %d\n",stu[n].name,stu[n].stdID,stu[n].Chinese,stu[n].Math,stu[n].Engish,stu[n].total);}char a[10];printf("请输入查找的名字:");scanf("%s",a);int low=1,high=i,mid;while(low<high) {mid=(low+high)/2;if(strcmp(a,stu[mid].name)==0) {printf("姓名\t学号\t语文\t数学\t英语\t总分\n");printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",stu[mid].name,stu[mid].stdID,stu[mid].Chinese,stu[mid].Math,stu[mid].Engish,stu[mid].total);break;} else if(strcmp(stu[mid].name,a)<0)low=mid+1;else high=mid-1;if(low==high)printf("Could not find!\n");//找不到返回}}//打印函数int PrintList_L(List p) {while(p) {printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish,p->std.total);p = p->next;}printf("\n");return 0;}//合并文件函数int combination() {FILE *fp1=fopen("E:\\1.txt","rb+"); //读入文件1.txtFILE *fp2=fopen("E:\\2.txt","rb+"); //读入文件2.txtFILE *fp3=fopen("E:\\3.txt","wb+"); //写入文件3.txtchar c;if(fp1==NULL||fp2==NULL||fp3==NULL) {puts("Could not open the files\n");return 0;}while((c=fgetc(fp1))!=EOF) //读到文件末尾返回EOF(-1)fputc(c,fp3); //逐个字符写入文件3.txtwhile((c=fgetc(fp2))!=EOF)fputc(c,fp3);printf("Merged 1.txt and 2.txt into 3.txt\n");fclose(fp1);fclose(fp2);fclose(fp3);return 1;}void menu() {system("cls"); //清屏信号printf("\n\n\n\n");printf("\t\t|------------------------STUDENT GRADE SYSTEM-------------------------------|\n");printf("\t\t|\t 0.退出 |\n");printf("\t\t|\t 1.合并1.txt和2.txt文件,生成3.txt文件|\n");printf("\t\t|\t 2.录入学生信息到链表 |\n");printf("\t\t|\t 3.抽取三科成绩中补考的学生(<60)保存到4.txt文件 |\n");printf("\t\t|\t 4.按总分降序排序(直接插入排序) |\n");printf("\t\t|\t 5.按总分降序排序(冒泡排序) |\n");printf("\t\t|\t 6.输入姓名,查找学生信息(直接查找) |\n");printf("\t\t|\t 7.输入姓名,查找学生信息(按姓名首字母排序并查找,二分查找) |\n");printf("\t\t|\t 8.输入姓名,查找学生信息(fibonacci查找) |\n");printf("\t\t|---------------------------------------------------------------------------|\n");printf("\t\t|======================请输入对应数字(0-7)==================================|\n");}int main() {List p;int n;menu();printf("请输入(0-7)>> ");scanf("%d",&n);while(1) {switch(n) {case 1: {combination();break;}case 2: {printf("姓名\t学号\t语文\t数学\t英语\t总分\n");p=inputfile();PrintList_L(p->next);break;}case 3: {bujige();break;}case 4: {printf("姓名\t学号\t语文\t数学\t英语\t总分\n");p=sortscore1();PrintList_L(p->next);break;}case 5: {printf("姓名\t学号\t语文\t数学\t英语\t总分\n");p=sortscore2();PrintList_L(p->next);break;}case 6:search_Name1();break;case 7:search_Name2();break;default:break;}if(n==0) break;getch();//过滤回车键menu();printf("请输入(0-7)>> ");scanf("%d",&n);}}
这是我的数据结构课设题目,想分享给大家参考,因为我觉得在这里分享会提高我对代码的兴趣,我也知道学习路上会有很多阻碍,非常感谢这个网站带来的帮助,我也希望帮助更多人,如有不足的地方,欢迎各位大神不吝赐教。