Bootstrap

学生成绩管理系统(合并文件,查找,总分排序,保存补考学生信息)

目录

题目及要求:

录入学生成绩信息到链表中

合并文件

直接插入排序(总分降序)

冒泡排序(总分降序)

顺序查找(名字查找)

二分查找(名字查找)

 这里是先按字母首字母排序再查找

保存不及格学生到文件中


题目及要求:

现有学生成绩信息文件 1(1.txt),内容如下(同学自己补充,共 30 名学生,数据文件格式与解析程序自己设定):

姓名

 学号

语文

数学

英语

张明明

01

 67

78

82

李成友

02

78

 91

 88

张辉灿

03

68

 82

56

王露

04

56

45

77

陈东明

 05

 67

 38

47

...

...

...

...

...

   学生成绩信息文件 2(2.txt),内容如下(同上):

姓名

 学号

语文

 数学

英语

陈果

31

 57

68

82

李华明

 32

 88

 90

68

张明东

33

48

 42

56

李明国

34

 50

45

87

陈道亮

 35

 47

 58

77

...

...

...

...

...

【实现要求】

试编写一管理系统,要求如下:

(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.txt
	FILE *fp2=fopen("E:\\2.txt","rb+");       //读入文件2.txt
	FILE *fp3=fopen("E:\\3.txt","wb+");       //写入文件3.txt
	char 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.txt
	while((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.txt
List 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.txt
	FILE *fp2=fopen("E:\\2.txt","rb+");       //读入文件2.txt
	FILE *fp3=fopen("E:\\3.txt","wb+");       //写入文件3.txt
	char 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.txt
	while((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);
	}
}

这是我的数据结构课设题目,想分享给大家参考,因为我觉得在这里分享会提高我对代码的兴趣,我也知道学习路上会有很多阻碍,非常感谢这个网站带来的帮助,我也希望帮助更多人,如有不足的地方,欢迎各位大神不吝赐教。

;