基于链表的的学生管理系统

基于链表的的学生管理系统

一、实验内容
编写并调试程序,实现学校各专业班级学生信息的管理。将10个学生的信息存储在文件studentInit.dat中;并定义学生信息的结构体类型,包括:学号、姓名、专业、班级、3门成绩;和符号常量N(学生数)。
#define N 10
struct Student{
char num[15];//学号
char name[15];//姓名
char major[10];//专业(computer,software,network)
int classNo;//班级(1-2)
int score[3];//3门课的成绩(0-2)
};
typedef struct Student STU;

二、实验要求
实验内容:编写并调试程序,实现学校各专业班级学生信息的管理。定义学生信息的链表结点类型,包括:学号、姓名、班级、专业、3门成绩。
实验要求:

(1)main函数:以菜单形式将各项功能提供给用户,根据用户的选择,调用相应的函数。
(2)定义函数void CreateList(int n):按学号由小到大,建立有序的链表。逆序输入n个学生信息(调用n次input),学号大的先输入,建立带头结点的单链表。
(3)定义函数void Output(STU *p):以指向某个学生结点的指针为参数,将学生信息格式化输出。
(4)定义函数void Save():将某个学生信息存入文件。
(5)定义函数void Fetch(int Index) :从文件中随机读取某个学生的信息。
(6)定义函数STU *Search_num(char num[]):查找指定学号的学生,返回指向该学生结点的指针。
(7)定义函数void InsertList():在函数中输入一个学生的信息,将该学生信息插入到链表中的相应位置,并保持此链表按学号的有序性。
(8)定义函数void Delete_num(char num[]):从链表中删除指定学号的学生。
(9)定义函数STU *Search_major_subject_score(char major[],int mm,int scorep):查找某个专业的、某门课程的成绩小于某个分数的学生,返回指向该学生结点的指针。
(10)定义函数void Delete_major_subject (char major[],int n,float scoreIn):从链表中删除某个专业的、某门课程的成绩小于某个分数的学生。
(11)定义函数void Welcome():实现菜单界面。
(12)定义函数void Input():输入学生信息,包括学号、姓名、专业、班级、三门课成绩。
(13)定义函数void Read():读取文件信息到链表中 。
(14)定义函数void Revise(char num[]):修改学生信息,利用学生学号的唯一性对学生可以进行姓名、专业、班级、三门成绩的修改。
(15)定义函数void Sort(int m,int n,int flag):学生信息排序,可以根据学生的学号、姓名、专业的字典序进行升序或者降序排序,也可以根据班级、三门课成绩进行升序或者降序排序。
(16)定义函数double Rate(int classNo,int ke,int x):班级优秀率和及格率查询。可以查询每个班级的的优秀率和及格率,也可以查询所有班综合的优秀率和及格率。
(17)void Browsing():查询历史用过的功能。
(18)void Clear():清空历史浏览记录

三、算法流程图
1学号的冒泡排序
在这里插入图片描述

2.学生信息的删除
在这里插入图片描述

四、程序清单

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
struct Student{
	char num[20];
	char name[20];
    char major[20];
	int classNo;
	float score[3];
	float sum;
	float aver;
	struct Student *next;	
}; 
struct History{
	char code[30];
	struct History*next;
};
typedef struct Student STU;
typedef struct History HTY;
STU *head;                          //定义链表头指针 
HTY *head_p=NULL;                        //定义历史浏览记录的头指针 
HTY *tail=NULL;                          //定义历史浏览记录的尾指针
char str[20][30]={"0.建立链表","1.从文件中读取信息到链表","2.输出全部学生信息","3.文件中随机读取学生信息","4.链表中指定学号查询","5.插入学生信息到链表","6.特定专业课程信息查询","7.链表中删除特定学生信息","8.学生信息排序 ","9. 优秀率及格率查询","10.修改学生信息 ","11.删除学生信息","12.保存学生信息到文件里"};

void welcome();                       //学生管理系统界面 
void CreateList(int n);               //按学号由小到大,建立有序的链表。逆序输入 n 个学生信息(调用n次input),学号大的先输入,建立带头结点的单链表。/
void Input(STU *p);                   //输入学生信息 
void Output(STU *p);                   //以指向某个学生结点的指针为参数,将学生信息格式化输出。
void Save();                          //将某个学生信息存入文件。
void Read();                           //读取文件信息到链表中 
void Fetch(int Index)  ;               //从文件中随机读取某个学生的信息/
STU *Search_num(char num[]);          //查找指定学号的学生,返回指向该学生结点的指针
void InsertList();                   //在函数中输入一个学生的信息,将该学生信息插入到链表中的相应位置,并保持此链表按学号的有序性。 
void Delete_num(char num[]) ;            //从链表中删除指定学号的学生。/
STU *Search_major_subject_score(char major[],int mm,int scorep);     //查找某个专业的、某门课程的成绩小于某个分数的学生,返回指向该学生结点的指针。 
void Delete_major_subject (char major[],int n,float scoreIn);       //从链表中删除某个专业的、某门课程的成绩小于某个分数的学生。
void Revise(char num[]);                      //修改学生信息
void Sort(int m,int n,int flag);                            //学生信息排序  1学号 2姓名 3专业 4班级 5成绩 
double Rate(int classNo,int ke,int x);                //及格率优秀率查询 
void Browsing();                                  //查询历史用过的功能 
void Clear();                                 //清空历史浏览记录 


int main(){
	while(1){
		welcome();
	}
	system("pause");
	return 0;
}

//学生管理系统界面 
void welcome(){
	int num;
	printf("  ***********************************************************\n");
	printf("  *                学生信息管理系统                         *\n");
	printf("  ***********************************************************\n\n");
	printf("  *******************系统功能菜单****************************\n");
	printf("     ----------------------   ------------------------------- \n");
	printf("     *****************************************************  \n");
	printf("     * 0.建立链表             * *  1.从文件中读取信息到链表  * \n");
	printf("     *****************************************************     \n");
	printf("     * 2.输出全部学生信息     * *  3.文件中随机读取学生信息  * \n");
	printf("     *****************************************************     \n");
	printf("     * 4.链表中指定学号查询   * *  5.插入学生信息到链表  * \n");
	printf("     *****************************************************     \n");
	printf("     * 6.特定专业课程信息查询 * *  7.链表中删除特定学生信息   * \n");
	printf("     *****************************************************     \n");
	printf("     * 8.学生信息排序         * *  9. 优秀率及格率查询        * \n");
	printf("     *****************************************************     \n");
	printf("     * 10.修改学生信息        * *  11.删除学生信息       * \n");
	printf("     *****************************************************     \n");
	printf("     * 12.保存学生信息到文件里* *  13.历史浏览记录查询   * \n");
	printf("     *****************************************************     \n");
	printf("     * 14.清空历史浏览记录    * *  15.退出程序           * \n");
	printf("     *****************************************************     \n");
	printf("     -----------------------------------------------------     \n");
	printf("请选择菜单编号:");
	scanf("%d", &num);
	HTY *ll;
	ll=(HTY *)malloc(sizeof(HTY));
	strcpy(ll->code,str[num]);
	if(head_p==NULL) {head_p=ll; tail=ll; tail->next=NULL;}
	else {tail->next=ll; tail=ll;tail->next=NULL;}
	switch (num)
	{
	case 0: 
	      printf("请问要输入几名学生信息:\n");
		  int n;
		  scanf("%d",&n);
		  CreateList(n); 
		  int aa;
		  printf("请选择是否保存信息到文件里:   1保存   2不保存\n");
		  scanf("%d",&aa);
		  switch(aa){
		  	case 1:
			    Save();
			    printf("\n\n信息保存成功!!!\n");
			    break;
		  	case 2:
				printf("\n\n信息没有保存\n\n");
			    break;
		  }
		  printf("\n\n\n\n");
		  system("pause");
		  break;
	case 1:
		 Read();
		 printf("读取信息成功!!!!\n\n\n\n\n");
		 system("pause");
		 break;
    case 2:
    	  printf("全部学生信息如下:\n");
	      printf("*************************************************************************************************************************\n");
       	  printf("*     学号     *   姓名  *   专业        *   班级   *   语文\t   *   数学      *   英语      *   平均分     *   总分\n");
	      STU *p,*q;
		  p=head;
	      while(p->next!=NULL){  
	     	Output(p);
	     	q=p->next;
	     	p=q;
		   }
		    Output(p);
		  	printf("*************************************************************************************************************************\n\n\n\n");
		   system("pause");
		   break;
	case 3:
		    printf("请输入要读取的序号:\n");
	    	int index;
	        scanf("%d",&index);
	        Fetch(index);
	        char t;
		    printf("按空格键退出查询,按其余键继续查询:\n");
		    t=getch();
	        while(t!=32){
			    printf("请输入要读取的序号:\n");
			    scanf("%d",&index);
			    Fetch(index);
			    printf("按空格键退出查询,按其余键继续查询:\n");
			    t=getch();
				printf("\n");
		   }
		    printf("\n\n");
		    system("pause");
		    break;
	case 4:
	        printf("请输入要查询的学生学号:\n");
	        char num[20];
	        scanf("%s",num);
	        printf("该学生信息如下:\n");
          	printf("*     学号     *   姓名  *   专业        *   班级   *   语文\t   *   数学      *   英语      *   平均分     *   总分\n");
			Output(Search_num(num));
			char tt;
		    printf("按空格键退出查询,按其余键继续查询:\n");
		    tt=getch();
	        while(tt!=32){
			    printf("请输入要查询的学生学号:\n");
			    scanf("%s",num);
			    printf("该学生信息如下:\n");
            	printf("*     学号     *   姓名  *   专业        *   班级   *   语文\t   *   数学      *   英语      *   平均分     *   总分\n");
			    Output(Search_num(num));
			    printf("按空格键退出查询,按其余键继续查询:\n");
			    tt=getch();
				printf("\n");
		   }
		   printf("\n\n\n");
		   system("pause");
		   break;
	case 5:
		    printf("请输入要插入的学生信息:\n");
		   	InsertList();
		   	printf("学生信息插入成功!!!\n");
		    int bb;		
		    printf("请选择是否保存信息到文件里:   1保存   2不保存\n");
		  	scanf("%d",&bb);
		 	switch(bb){
		  	case 1:
			    Save();
			    printf("信息保存成功!!!\n");
			    break;
		  	case 2:
		  		printf("\n\n信息没有保存\n\n");
			    break;
		  }
		   	printf("\n\n\n\n");
		   	system("pause");
		   	break;
	case 6:
	       printf("请输入要查询的专业名称:\n");
		   char major_p[20];
		   scanf("%s",major_p);
		   printf("请输入要查询的课程序号(0语文 1数学 2英语):\n");
		   int mm;
		   scanf("%d",&mm);
		   printf("请输入临界分:\n");
		   int scorep;
		   scanf("%d",&scorep);
		   printf("%s专业里该课程分数小于%d的学生信息如下:\n",major_p,scorep); 
		   printf("*************************************************************************************************************************\n");
           printf("*     学号     *   姓名  *   专业        *   班级   *   语文\t   *   数学      *   英语      *   平均分     *   总分\n");
		   Output(Search_major_subject_score(major_p,mm,scorep) );
		   printf("*************************************************************************************************************************\n\n\n\n");
		   system("pause");
		   break;
	case 7:
	       char major[20];
		   int m;
		   float scoreIn;
		   printf("请输入专业名称:\n");
		   scanf("%s",major) ;
		   printf("请输入课程序号(0语文 1数学 2英语):\n");
		   scanf("%d",&m);
		   printf("请输入边界分数:\n");
		   scanf("%f",&scoreIn);
		   printf("\n%s专业中该课程分数小于%.2f分的人删除情况如下:\n",major,scoreIn); 
		   Delete_major_subject (major,m,scoreIn);
		    int cc;		
		    printf("请选择是否保存信息到文件里:   1保存   2不保存\n");
		  	scanf("%d",&cc);
		 	switch(cc){
		  	case 1:
			    Save();
			    printf("信息保存成功!!!\n");
			    break;
		  	case 2:
		  		printf("\n\n信息没有保存\n\n");
			    break;
		  }
		   printf("\n\n\n\n");
		   system("pause");
		   break;
	case 8:
	    printf("请选择哪种基准排序:	1.学号	2.姓名	3.专业	4.班级	5.成绩\n");
		int xx;
		scanf("%d",&xx);
		printf("请选择排序方式:	1.升序排序(从小到大)	2.降序排序(从大到小)\n");
		int yy;
		scanf("%d",&yy);
		if(xx!=5) {
			Sort(xx,yy,0); 
		}
		else {
			int flag;
			printf("请选择哪种基准:	0.语文	1.数学	2.英语\n");
			scanf("%d",&flag);
			Sort(xx,yy,flag); 
		}
		    printf("学生信息排序成功!!!\n\n");
	        int ee;		
		    printf("请选择是否保存信息到文件里:   1保存   2不保存\n");
		    scanf("%d",&ee);
		    switch(ee){
		    case 1:
			    Save();
			    printf("信息保存成功!!!\n");
		 	    break;
		  	case 2:
		  		printf("\n\n信息没有保存\n\n");
			    break;
		  }
		  printf("\n\n\n\n");
		  system("pause");
	      break;
	case 9:
		    printf("请输入要查询的班级:(1 2 3)	4(综合即三个班一起)\n"); 
		    int pp;
		    scanf("%d",&pp);
		    printf("请输入要查询的课程:	0.语文	1.数学	2.英语\n"); 
		    int nn;
		    scanf("%d",&nn);
		    printf("请输入查询:		1.及格率	2.优秀率\n");
            int ff;
            scanf("%d",&ff);
            if(ff==1) printf("及格率为:\n%.2lf",Rate(pp,nn,ff));
			else printf("优秀率为:\n%.2lf",Rate(pp,nn,ff)); 
		    printf("\n\n\n");
		    system("pause");
		    system("cls");
		    break;
	case 10:
	        printf("请输入需要修改信息的学生学号:\n");
	        char num_pp[20];
	        scanf("%s",num_pp);
	        Revise(num_pp);
	        printf("\n\n\n\n");
	        system("pause");
	        break;
	case 11:
		   printf("请输入要删除信息的学生学号:\n");
		   char num_p[20];
		   scanf("%s",num_p);
		   Delete_num(num_p);
		   int dd;		
		   printf("请选择是否保存信息到文件里:   1保存   2不保存\n");
		   scanf("%d",&dd);
		   switch(dd){
		    case 1:
			    Save();
			    printf("信息保存成功!!!\n");
		 	    break;
		  	case 2:
		  		printf("\n\n信息没有保存\n\n");
			    break;
		  }
		   printf("\n\n\n\n");
		   system("pause");
		   break;
	case 12:
		  Save();
		  printf("所有信息已经写入文件中!!!\n\n\n");
		  break;
	case 13:
	      printf("历史浏览记录如下:\n");
	      Browsing();
	      printf("\n\n\n\n");
	      system("pause");
	      break;
	case 14:
	      Clear();
		  printf("历史浏览记录已经删除!!!\n\n\n\n");
		  system("pause");
		  break;	
	case 15:
	    printf("即将退出程序!\n");
		exit(0);
	default:printf("请在0-14之间选择\n\n\n");
	}
}


//按学号由小到大,建立有序的链表。逆序输入 n 个学生信息(调用n次input),学号大的先输入,建立带头结点的单链表。
void CreateList(int n){
	STU *p1,*p2,*p3,*p4,p5,*p6;
	head=NULL;
	p1=p2=(STU *)malloc(sizeof(STU));
	for(int i=0;i<n;i++){
		Input(p1);
		if(head==NULL) head=p1;
		else p2->next=p1;
		p2=p1;
		p1=(STU *)malloc(sizeof(STU)); 
	}
	p2->next=NULL;
	if(n==0) {
		printf("Input error!Please try again!\n\n\n");
		return ; 
	}
    printf("\n\n\n");
    int x;
	printf("请选择:1.顺序建表	2.逆序建表\n");
	scanf("%d",&x);
	switch(x){
		case 1:
			for(p3=head;p3;p3=p3->next){
				for(p4=p3->next;p4;p4=p4->next){
				if(strcmp(p3->num,p4->num)>0){
					p5=*p3;
					*p3=*p4;
					*p4=p5;
					p6=p3->next;
					p3->next=p4->next;
					p4->next=p6;
				}
			}
		}
		break;
		case 2:
			for(p3=head;p3;p3=p3->next){
				for(p4=p3->next;p4;p4=p4->next){
				if(strcmp(p3->num,p4->num)<0){
					p5=*p3;
					*p3=*p4;
					*p4=p5;
					p6=p3->next;
					p3->next=p4->next;
					p4->next=p6;
				}
			}
		}
		break;
	}
	 printf("\n\n学生信息录入链表成功\n"); 
}

//输入学生信息
void Input(STU *p){
	printf("请输入学号:\n");
	scanf("%s",p->num);
	printf("请输入姓名:\n");
	scanf("%s",p->name);
	printf("请输入专业:\n");
	scanf("%s",p->major);
	printf("请输入班级:\n");
	scanf("%d",&p->classNo);
	printf("请输入三门成绩(语文、数学、英语):\n");
	scanf("%f%f%f",&p->score[0],&p->score[1],&p->score[2]);
}

//以指向某个学生结点的指针为参数,将学生信息格式化输出。
void Output(STU *p){
	p->sum=p->score[0]+p->score[1]+p->score[2];
	p->aver=p->sum/3;
    if(p!=NULL) printf("*   %s   *   %s   *   %s\t *      %d   *   %-6.2f     *    %-6.2f   *   %-6.2f    *     %-6.2f   *     %-6.2f\n\n",(*p).num,(*p).name,(*p).major,(*p).classNo,(*p).score[0],(*p).score[1],(*p).score[2],(*p).aver,(*p).sum);
    else printf("该学生不存在!!!\n\n");
}   

 //从文件中随机读取某个学生的信息
void Fetch(int Index){
	STU *pt=head,*p;
	FILE *fp;
	if((fp=fopen("student.txt","rb"))==NULL){
		printf("can not open file\n");
		exit(0);
	}
        printf("该学生信息如下:\n");
     	printf("*************************************************************************************************************************\n");
       	printf("*     学号     *   姓名  *   专业        *   班级   *   语文\t   *   数学      *   英语      *   平均分     *   总分\n");
	    fseek(fp,Index*sizeof(STU),0);             			//移动文件位置标记,从头开始
	    for(int i=0;i<Index;i++){
		p=pt->next;
		pt=p;
	}

	Output(pt);
	fclose(fp);
}

//将某个学生信息存入文件。
void Save(){
	FILE *fp;
	STU *p1=head,*p2;
	p2=p1->next;
	if((fp=fopen("student.txt","wb"))==NULL){
		printf("error!");
		exit(0);
	}
	while(p1->next!=NULL){
		if(fwrite(p1,sizeof(STU),1,fp)!=1){
			printf("error!!!"); 
		}
		p1=p2;
		p2=p1->next;
	}
	if(fwrite(p1,sizeof(STU),1,fp)!=1){
		printf("error!!!"); 
		}
	fclose(fp);
}

//读取文件信息到链表中 
void Read(){
        FILE *fp;
        STU *p1=head,*p2;
	    if((fp=fopen("student.txt","rb"))==NULL)
	    {
			printf("cannot open file\n");
			exit(0);
	    }
	    while(p1->next!=NULL){
	      	fread(p1,sizeof(STU),1,fp);
	      	p2=p1->next;
	      	p1=p2;
		} 
		printf("\n\n\n文件读取成功\n\n\n\n\n");
		fclose(fp);
}

//查找指定学号的学生,返回指向该学生结点的指针
STU *Search_num(char num[]){
	STU *p1=head,*p2;
	p2=p1->next;
	while(p2!=NULL){
		if(strcmp(p2->num,num)==0){
			return (p2);
		}
		p1=p2;
		p2=p1->next;
	}
	if(strcmp(head->num,num)==0)	return (head);
}

//从链表中删除指定学号的学生。
void Delete_num(char num[]){
	STU *p1=head,*p2;
	int flag=0;
	while(p1!=NULL){
		if(strcmp(p1->num,num)==0)
		{
			flag=1;
			if(p1==head) head=p1->next;
			else if(p1->next==NULL){
				p1=p2;
				p1->next=NULL;
			}
			else {
				p2->next=p1->next;
			}
	}
	
		p2=p1;
		p1=p1->next;
}
     if(flag==1) printf("\n该学生信息删除成功!!!\n\n\n");
     else printf("\n您输入的学号不存在!!!\n\n\n");
}

//在函数中输入一个学生的信息,将该学生信息插入到链表中的相应位置,并保持此链表按学号的有序性。
void InsertList(){
	STU *pt;
	STU *p,*q,*pp;
	STU s;
	pt=(STU*)malloc(sizeof(STU));
	Input(pt);
	pt->next=head;
	head=pt;
	printf("\n\n\n");
    int x;
	printf("请选择:1.顺序建表	2.逆序建表\n");
	scanf("%d",&x);
	switch(x){
		case 1:
			for(p=head;p;p=p->next){
				for(q=p->next;q;q=q->next){
				if(strcmp(p->num,q->num)>0){
					s=*p;
					*p=*q;
					*q=s;
					pp=p->next;
					p->next=q->next;
					q->next=pp;
				}
			}
		}
		break;
		case 2:
			for(p=head;p;p=p->next){
				for(q=p->next;q;q=q->next){
				if(strcmp(p->num,q->num)<0){
					s=*p;
					*p=*q;
					*q=s;
					pp=p->next;
					p->next=q->next;
					q->next=pp;
				}
			}
		}
		break;
	}
}   

//查找某个专业的、某门课程的成绩小于某个分数的学生,返回指向该学生结点的指针。               
STU *Search_major_subject_score(char major[],int n,int score){
	STU *p1=head;
	STU *pt=NULL;          //记录第一个符合条件的指针
	int flag=0; 
	while(p1!=NULL){
		if(strcmp(p1->major,major)==0&&p1->score[n]<=score){
			if(pt==NULL)  pt=p1;
			else Output(p1);
			flag=1;
		}
		p1=p1->next;
	}
	if(flag==1)  return pt;
	else return NULL;
}

//从链表中删除某个专业的、某门课程的成绩小于某个分数的学生。  
void Delete_major_subject (char major[],int n,float scoreIn){
	STU *p1=head,*p2;
	int flag=0;
	while(p1!=NULL){
		if(strcmp(p1->major,major)==0&&p1->score[n]<=scoreIn)
		{
			if(p1==head) head=p1->next;
			else if(p1->next==NULL){
				p1=p2;
				p1->next=NULL;
			}
			else {
				p2->next=p1->next;
				 
			}
				flag++;
	    }  
	   
		p2=p1;
		p1=p1->next;
		
}
     printf("学生信息删除成功!!!一共删除了%d名学生的信息!!!\n\n\n\n",flag);
} 

//修改学生信息
void Revise(char num[]){
	STU *p=head; 
	int flag=0;
	while(p!=NULL)
	{
		if(strcmp(p->num,num)==0)
		{
			flag=1;
			printf("该学生的全部信息如下:\n");
			printf("*     学号     *   姓名  *   专业        *   班级   *   语文\t   *   数学      *   英语      *   平均分     *   总分\n");
			Output(p);
			printf("请选择需要修改的内容:\n	1.修改姓名	2.修改专业(software、nurse、teacher)	3.修改班级(1、2、3)	4.修改成绩\n");
			int x;
			scanf("%d",&x);
			switch(x){
				case 1:
					printf("请输入新名字:\n");
					char newname[20];
					scanf("%s",newname);
					strcpy(p->name,newname); 
					printf("\n\n名字修改成功!!!\n\n");
					break;
				case 2:
					printf("请输入新专业:\n");
					char newmajor[20];
					scanf("%s",newmajor);
					strcpy(p->major,newmajor);
					printf("\n\n专业修改成功!!!\n\n");
					break;
				case 3:
					printf("请输入新班级:\n");
					int newclass;
					scanf("%d",&newclass);
					p->classNo=newclass;
					printf("\n\n班级修改成功!!!\n\n");
					break;
				case 4:
					printf("请输入需要修改成绩的课程:\n		0.语文	 1数学	2英语\n");
					int n;
					scanf("%d",&n);
				    switch(n){
				    	case 0:
				    		printf("请输入新的语文成绩:\n");
				    		int newscore0;
				    		scanf("%d",&newscore0);
				    		p->score[0]=newscore0;
				    		break;
				    	case 1:
				    		printf("请输入新的数学成绩:\n");
				    		int newscore1;
				    		scanf("%d",&newscore1);
				    		p->score[1]=newscore1;
				    		break;
				    	case 2:
				    		printf("请输入新的英语成绩:\n");
				    		int newscore2;
				    		scanf("%d",&newscore2);
				    		p->score[2]=newscore2;
				    		break;
					}
					printf("\n\n成绩修改成功!!!\n\n");
				    break;
			}
		   char ch; 
		   printf("按空格键退出修改,按其余键继续修改:\n");
		   ch=getch();
		   while(ch!=32){
			printf("请选择需要修改的内容:\n	1.修改姓名	2.修改专业(software、nurse、teacher)	3.修改班级(1、2、3)	4.修改成绩\n");
			int x;
			scanf("%d",&x);
			switch(x){
				case 1:
					printf("请输入新名字:\n");
					char newname[20];
					scanf("%s",newname);
					strcpy(p->name,newname); 
					printf("\n\n名字修改成功!!!\n\n");
					break;
				case 2:
					printf("请输入新专业:\n");
					char newmajor[20];
					scanf("%s",newmajor);
					strcpy(p->major,newmajor);
					printf("\n\n专业修改成功!!!\n\n");
					break;
				case 3:
					printf("请输入新班级:\n");
					int newclass;
					scanf("%d",&newclass);
					p->classNo=newclass;
					printf("\n\n班级修改成功!!!\n\n");
					break;
				case 4:
					printf("请输入需要修改成绩的课程:\n		0.语文	 1数学	2英语\n");
					int n;
					scanf("%d",&n);
				    switch(n){
				    	case 0:
				    		printf("请输入新的语文成绩:\n");
				    		int newscore0;
				    		scanf("%d",&newscore0);
				    		p->score[0]=newscore0;
				    		break;
				    	case 1:
				    		printf("请输入新的数学成绩:\n");
				    		int newscore1;
				    		scanf("%d",&newscore1);
				    		p->score[1]=newscore1;
				    		break;
				    	case 2:
				    		printf("请输入新的英语成绩:\n");
				    		int newscore2;
				    		scanf("%d",&newscore2);
				    		p->score[2]=newscore2;
				    		break;
					}
					printf("\n\n成绩修改成功!!!\n\n");
				    break;
			}
			    printf("按空格键退出修改,按其余键继续修改:\n");
			    ch=getch();
				printf("\n");
		   }
			break;
		}
		p=p->next;
		
	}
	if(flag==1){
		 printf("请选择是否保存信息到文件里:   1保存   2不保存\n");
		 int m;
		 scanf("%d",&m);
		 switch(m){
		 	case 1:
		 		Save();
		 		printf("\n\n修改后信息已经保存\n\n");
		 		break;
		 	case 2:
		 		printf("\n\n信息没有保存\n\n");
		 		break;
		 }
	} 
	else if(flag==0) printf("该学生不存在!!!\n\n");
	
}  

//学生信息排序
void Sort(int m,int n,int flag){   //m代表基准 n代表升序和降序  flag专用于成绩查询方式   
	STU *p,*q,*r;
	STU s;                 //基准 1学号 2姓名 3专业 4班级 5成绩 	   //1升序 2降序 
	if(m<5){
	for(p=head;p;p=p->next){
		for(q=p->next;q;q=q->next){
		if(((m==1&&n==1)&&(strcmp(p->num,q->num)>0))||((m==1&&n==2)&&(strcmp(p->num,q->num)<0))||((m==2&&n==1)&&(strcmp(p->name,q->name)>0))||((m==2&&n==2)&&(strcmp(p->name,q->name)<0))||((m==3&&n==1)&&(strcmp(p->major,q->major)>0))||((m==3&&n==2)&&(strcmp(p->major,q->major)<0))||((m==4&&n==1)&&(p->classNo>q->classNo))||((m==4&&n==2)&&(p->classNo<q->classNo))) 
		{
			s=*p;
			*p=*q;
			*q=s;
			r=p->next;
			p->next=q->next;
			q->next=r;
			}
		}
	 } 
	}
    else if(m==5&&n==1){   
	      //成绩升序 
	  for(p=head;p;p=p->next){
		for(q=p->next;q;q=q->next){		
	        if(p->score[flag]>q->score[flag]){	
			s=*p;
			*p=*q;
			*q=s;
			r=p->next;
			p->next=q->next;
			q->next=r;
			}
		}
	}
	}
	else if(m==5&&n==2){         //成绩降序 
	  for(p=head;p;p=p->next){
		for(q=p->next;q;q=q->next){		
	        if(p->score[flag]<q->score[flag])
	        {	
			s=*p;
			*p=*q;
			*q=s;
			r=p->next;
			p->next=q->next;
			q->next=r;
			}
		}
		}
	}
} 

  //及格率优秀率查询
double Rate(int classNo,int ke,int x){ //1 2 3班级 4(综合)   x=1及格率 x=2优秀率 
 	STU *p=head;
    if(classNo==4){
    	if(x==1){
    		int a=0,b=0;        //a记录总人数  b记录符合要求的人数 
    		while(p!=NULL){
    			a++;
    			if(p->score[ke]>=60) b++;
    			p=p->next;
			}
			return ((1.0)*b/a);
		}
		else if(x==2){
			int a=0,b=0;        //a记录总人数  b记录符合要求的人数 
    		while(p!=NULL){
    			a++;
    			if(p->score[ke]>=90) b++;
    			p=p->next;
			}
			return ((1.0)*b/a);
		}
	}
    else{
    	if(x==1){
    		int a=0,b=0;        //a记录总人数  b记录符合要求的人数 
    		while(p!=NULL){
    			if(p->classNo==classNo){				
				   a++;
    			   if(p->score[ke]>=60) b++;
    	           	}
    		       p=p->next;
			}
			return ((1.0)*b/a);
		}
    	else if(x==2){
    		int a=0,b=0;        //a记录总人数  b记录符合要求的人数 
    		while(p!=NULL){
    		    if(p->classNo==classNo){		    	
			        a++;
    			    if(p->score[ke]>=90) b++;
				}
    			p=p->next;
			}
			return ((1.0)*b/a);
	}
 } 
}

//历史浏览记录查询
void Browsing(){
	HTY *p=head_p; 
	while(p!=NULL){
	printf("%s\n",p->code);
	p=p->next;
	}
} 
void Clear(){
	HTY *p=head_p,*pt;
	while(p!=NULL){
		pt=p->next;
		free(p);
		p=NULL;
		p=pt;
	}
}
/*
22202021
zyy
software
1
78 45 90
22229083
dxs
teacher
2
45 65 78
22239067
jik
software
3
34 76 98
22220976
shw
nurse
2
89 65 78
22229032
fdc
teacher
1
67 78 65
22230877
scd
nurse
3
99 87 99
22228766
rnk
software
2
67 87 99
22228977
rmd
teacher
1
89 76 88 
22225768
zjj
nurse
1
78 67 65
22226123
wws
software
3
56 76 56
 */                     

五、实验总结与分析(所设计系统的特色之处,实验过程中遇到的具体问题及解决方法)
1.特色:该基于链表的学生管理系统,在实验要求的几大函数功能的基础上添加了Revise()函数、Read()函数、Sort()函数、Rate()函数、Browsing()函数和Clear()函数,分别实现了在链表中修改学生信息,读取文件信息到链表中,对所有学生基于学号、姓名、专业、班级、三门成绩进行升序或者降序排序,某一个班级或者所有班级的综合优秀率和及格率查询,历史浏览记录查询、删除历史浏览记录等6大新功能。

对于新功能一:从链表的头指针遍历到尾指针,利用链表中学生学号的唯一性进行匹配,从而对匹配的学生进行姓名、专业、班级、三门成绩进行修改。由于增添了getch()函数,可以让我们在不按空格键的情况下继续修改该学生的信息,无需再返回菜单页面,使修改学生信息更为灵活、方便。
对于新功能二:可以随时随地将文件中的二进制信息读取到链表中,这样可以在文件里的信息被更改过后得以被准确无误的读取并加以利用。
对于新功能三:通过一个链表的冒泡排序,使所有学生按照学号、姓名、专业的字典序进行升序或者降序排序,以及按照班级、三门成绩的大小进行升序或者降序排序。
对于新功能四:可以查询每一个班级里的学生的优秀率以及及格率进行评比,也可以查询所有班级里的学生的优秀率以及及格率。
对于新功能五:通过再额外建立一个链表HTY,以及用一个二维字符数组记录每一项菜单编号的功能和选项,可以在我们每次选择菜单功能的时候记录到链表当中,从而实现历史使用的菜单以及功能查询。
对于新功能六:通过遍历额外链表HTY的每一个块内存,然后使链表的每一块内存都free()掉,并且让他们的指针为NULL;从而实现了随时随地可以清空历史浏览记录。
当然,该学生管理系统还有两个亮点。一个就是只要修改了链表里的学生信息,无论是修改、增添还是删除,都可以选择是否保存到文件里;还一个就是getch()的利用,它可以使每一个字符都无需按回车键便被输入,包括回车键也是一个字符;而scanf或者getchar()都需要在输入字符的时候再按回车键才算被输入,可以提高我们查询、修改、增添、删除学生信息的效率,无需再返回菜单页面选择功能。

2.问题与解决方法

问题一:用CreateList()函数建立链表时,要求根据学号大小建立有序的链表时,虽然我们会冒泡排序、选择排序以及插入排序,但对于链表来说,它是动态的,用排序交换两个内存的时候,它们的下一个指针连接点却没有变,导致链表混乱,从而无法排序成功。
解决方法:定义一个结构体STU
s,以及一个结构体指针STUpt,使用s作为替代品交换两块内存时,再用pt将两块内存的下一个连接点指针交换回来,这样就可以再链表不改变的基础上只是交换了两块内存的数据域,指针域没有改变。
问题二:用Fetch()函数从文件中随机读取某个学生信息时,因为文件里的信息是二进制数据,要想查询某个学生信息时需要找到它在链表中的指针在文件里的位置。
解决方法:通过fseek()函数从文件的开头开始读取,跳到你需要查询的学生信息的数据,通过fread()读取这块信息到链表中。
问题三:用Save()函数保存链表中的信息到文件里时,通过fwrite()函数写入会覆盖之前的信息,导致每次调用这个函数时文件里的信息都会焕然一新,而不是在原有信息上添加。
解决方法:通过定义结构体指针STU p,将链表的头指针赋值给它,再通过它遍历链表中的每一块内存信息,全部写入到文件里。
问题四:用函数Delete_num()在链表中删除指定学号的学生信息时,由于该学生信息可能在链表的头部、中间、尾部三种情况,所以只是将要删除区域的后一个连接点赋值给前一个的连接点,也就是next,只能解决中间部分的学生信息的删除。
解决方法:对于第一种情况,要删除的学生信息是链表的头指针所在区域,则将头指针head指向head->next;对于第三种情况,要删除的学生信息是链表的尾指针所在区域,则让尾指针为NULL,再将尾指针提前一个。
问题五:用Search_major_subject_score()函数查找链表中指定专业课程里小于特定分的学生信息,由于函数返回值类型是结构体指针STU
型,所有在有多个学生满足条件时只能返回一个学生信息的指针。
解决方法:定义一个结构体指针STU
pt,作为链表里第一个符合条件的学生的指针并作为返回值返回,而如果还有其他符合条件的学生则直接调用Output()函数输出。
问题六:用Sort()函数给所有学生按照学号、姓名、专业、班级、三门成绩排序时由于情况众多,需要写十多个相同的冒泡排序,导致代码冗长。
解决方法:给该函数定义三个参数m,n,flag,m是选择学号、姓名、班级、专业、三门成绩的基准,n是选择升序还是降序,flag则是在选择成绩排序时所选择的课程序号基准,然后用一个if语句通过||以及&&将每种情况都||掉,使代码只需要写一次就好。
问题七:用Browsing()函数记录历史用过的菜单功能及编号时,每次记录都需要根据不同的菜单编号给该额外链表的数据域赋值,由于菜单功能繁多,要分十多种情况,特别不方便。
解决方法:定义了一个二维字符数组s,一维记录菜单编号,一维记录菜单功能,则每次调用菜单功能也就是选择菜单编号k时就可以直接将s[k]的内容strcpy给链表的尾指针的数据域,再让尾指针tail=tail->next;
问题八:为了让修改、删除和增添学生信息时可以按回车键再继续进行,只有按空格键才重新回到菜单,我们一直试用scanf和getchar()函数输入字符时,必须再按回车键才算输入,并且不识别回车键这个字符。
解决方法:添加头文件#include<conio.h>,使用getch()函数识别并且输入字符,可以识别回车键这个字符,也可以在不按回车键的情况下输入字符。

学生成绩管理系统是一个常见的应用程序,用于存储和处理学生的成绩信息。基于链表学生成绩管理系统可以使用链表数据结构来有效地组织和管理学生的成绩数据。每个节点可以存储一个学生的成绩信息,包括学号、姓名、科目和分数等。 下面是一个简单的基于链表学生成绩管理系统的示例代码: ```python class Node: def __init__(self, student_id, name, subject, score): self.student_id = student_id self.name = name self.subject = subject self.score = score self.next = None class GradeManagementSystem: def __init__(self): self.head = None def add_student(self, student_id, name, subject, score): new_node = Node(student_id, name, subject, score) if self.head is None: self.head = new_node else: current = self.head while current.next is not None: current = current.next current.next = new_node def remove_student(self, student_id): if self.head is None: return if self.head.student_id == student_id: self.head = self.head.next return current = self.head while current.next is not None: if current.next.student_id == student_id: current.next = current.next.next return current = current.next def get_student_score(self, student_id): current = self.head while current is not None: if current.student_id == student_id: return current.score current = current.next return None def print_all_students(self): current = self.head while current is not None: print(f"Student ID: {current.student_id}") print(f"Name: {current.name}") print(f"Subject: {current.subject}") print(f"Score: {current.score}") print("---------------") current = current.next # 示例用法 grade_system = GradeManagementSystem() grade_system.add_student(1, "Alice", "Math", 90) grade_system.add_student(2, "Bob", "English", 85) grade_system.print_all_students() ``` 这是一个简单的例子,你可以根据实际需求扩展和修改代码。这个示例中的学生成绩信息是按照添加顺序存储的,你也可以根据需求进行其他排序方式的实现
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

&が&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值