文章目录
前言
续上一个文章,头文件主函数在上一个文章中。
C语言学生管理系统(文件、链表)-(1)管理员
一、教师功能介绍
1.教师登录
这里通过遍历文件内容查找;
输出错误提示是否重新输入。
2.修改教师密码
实现链表和文件的修改密码操作。
3.输入学生信息
实现学号不重复操作,将学生信息录入链表和文件(若文件中有数据则在后边继续添加);
在添加中设置了常规的输入限制。
4.删除学生信息
实现删除链表和文件的相关信息,这里同样因为学号的唯一性,以学号为检索条件。
5.查询学生信息
这里使用链表执行排序操作并显示链表,并不会影响文件里的数据
注:
链表的使用对于进行中间的一些文件操作有很大的便利性,但是实际还是得对文件增删改查,链表在这里主要使用在了查的操作中。
二、具体代码
包含头文件:
#include"../inc/admin.h"
#include"../inc/teacher.h"
#include"../inc/student.h"
1.教师菜单(main功能2)
代码如下:
/*
函数功能:教师菜单
函数参数:无
返回值:无
*/
void teacher_menu(long id,struct node1*head_t,struct node2*head_s)
{
int flag=1;
int code;
while(flag)
{
printf("\n");
printf("**欢迎进入教师界面**\n");
printf("1.修改密码.\n");
printf("2.添加新学生.\n");
printf("3.删除学生.\n");
printf("4.查询学生信息.\n");
printf("5.修改学生信息.\n");
printf("6.查看学生信息.\n");
printf("0.返回上一级.\n");
printf("**********************\n");
printf("请输入你的选择:");
scanf("%d",&code);
while(getchar()!='\n');
switch(code)
{
case 1:{
modify_teacher_password(head_t, id);
break;
}
case 2:{
add_student_link(head_t,head_s);
break;
}
case 3:{
long id;
printf("请输入你想删除的学生的学号:");
scanf("%ld",&id);
while(getchar()!='\n');
delete_student(head_s,id);
break;
}
case 4:{
long id;
printf("请输入你想查询的学生的学号:");
scanf("%ld",&id);
while(getchar()!='\n');
seacher_student_id_link(head_s,id);
break;
}
case 5:{
long id;
printf("请输入你想修改的学生的学号:");
scanf("%ld",&id);
while(getchar()!='\n');
modify_student(head_s,id);
break;
}
case 6:{
//show_student();//测试文件内容
int flag1=1;
int code1;
while(flag1)
{
printf("\n");
printf("********你可以以下列方式查询********\n");
printf("1.按学号从低到高查看所有学生信息.\n");
printf("2.按数学成绩从高到低查看所有学生信息.\n");
printf("3.按语文成绩从高到低查看所有学生信息.\n");
printf("4.按英语成绩从高到低查看所有学生信息.\n");
printf("5.按总分从高到低查看所有学生信息.\n");
printf("0.返回上一级.\n");
printf("************************************\n");
printf("请输入你的选择:");
scanf("%d",&code1);
while(getchar()!='\n');
switch(code1)
{
case 1:{
head_s=show_by_id(head_s);
show_student_link(head_s);
break;
}
case 2:{
head_s= show_by_math(head_s);
show_student_link(head_s);
break;
}
case 3:{
head_s=show_by_Chinese(head_s);
show_student_link(head_s);
break;
}
case 4:{
head_s=show_by_English(head_s);
show_student_link(head_s);
break;
}
case 5:{
head_s=show_by_sum(head_s);
show_student_link(head_s);
break;
}
case 0:{
flag1=0;
break;
}
default:{
printf("输入有误,请重新输入:");
scanf("%d",&code1);
while(getchar()!='\n');
break;
}
}
}
break;
}
case 0:{
flag=0;
break;
}
default:{
printf("输入有误,请重新输入:");
scanf("%d",&code);
while(getchar()!='\n');
break;
}
}
}
}
2.教师登录
代码如下(示例):
/*
函数功能:读取教师
函数参数:教师结构体变量,要读取的教师工号
返回值:无
*/
void read_teacher(Teacher *t,long id)
{
FILE *fp=NULL;
int ret;
fp=fopen("teacher.txt","r");//打开文件读取预存的账户和密码
assert(fp!=NULL);//判断文件是否已经打开
while(1)
{
ret=fscanf(fp,"%ld %s %s %u-%u-%u %s\n",&(t->badge),t->name,t->gender,&((t->birth).year),&((t->birth).month),&((t->birth).day),t->password);
if(t->badge==id)
{
//printf("找到此人!\n");//测试
fclose(fp);
return;
}
if(ret<=0)
{
printf("查无此人!\n");
fclose(fp);
return;
}
}
}
/*
函数功能:教师登陆
函数参数:(用于记录输入的信息)
返回值:登陆成功返回1,失败返回0
函数说明:这里预设的教师的id会被修改
*/
bool login_teacher(long *id)
{
char password[15];
Teacher t;//用于存放从文件读取的教师信息
int n=3;//最高重新输入的次数
char ch;//是否重新输入
//登陆,输入工号和密码
printf("请输入工号:");
scanf("%ld",id);//记录输入的工号
while(getchar()!='\n');
printf("请输入密码(最多15个字符或数字):");
scanf("%s",password);//记录输入的密码
while(getchar()!='\n');
read_teacher(&t,*id);//读取文件中的教师信息
while(t.badge!=*id||strcmp(t.password,password)!=0)//如果输入与预存的不符合执行循环
{
printf("登陆失败!\n");
printf("您还有%d次重新输入的机会!\n",n);
printf("是否重新输入(y/n):");
scanf("%c",&ch);
while(getchar()!='\n');
if(ch=='n'||ch=='N')//判断是否重新输入
{
return false;
}
if(n==0)
{
return false;
}
printf("请输入工号:");
scanf("%ld",id);//记录输入的工号
while(getchar()!='\n');
printf("请输入密码:");
scanf("%s",password);//记录输入的密码
while(getchar()!='\n');
n--;
}
return true;
}
3.修改教师信息(teacher功能1)
包含文件和链表操作:
/*
函数功能:修改文件中指定教师的登陆密码
函数参数:要修改的教师的工号(为了排除链表查找的影响直接用id),新的密码数组
返回值:无
函数说明:通过临时文件和结构体实现修改操作
*/
void modify_teacher_password_file(long id,char password[])
{
FILE *fp=NULL,*ft=NULL;
int ret1;
Teacher set;
fp=fopen("teacher.txt","rt+");//读写方式打开一个文本文件,允许读写
ft=fopen("temp1.txt","wt");//以只写打开或建立一个文本文件,只允许写
assert(fp!=NULL&&ft!=NULL);
while(1)
{
ret1=fscanf(fp,"%ld %s %s %u-%u-%u %s\n",&(set.badge),set.name,set.gender,&((set.birth).year),&((set.birth).month),&((set.birth).day),set.password);
if(ret1<=0)
{
// printf("文件查无此人!\n");//测试
break;
}
if(set.badge==id)
{
strcpy(set.password,password);
}
fprintf(ft,"%ld %s %s %u-%u-%u %s\n",set.badge,set.name,set.gender,(set.birth).year,(set.birth).month,(set.birth).day,set.password);
}
fclose(fp);
fclose(ft);
remove("teacher.txt");
rename("temp1.txt","teacher.txt");
//printf("文件修改成功!\n");//测试
return;
}
/*
函数功能:修改教师密码
函数参数:教师链表的头结点地址,要修改的教师id
返回值:无
*/
void modify_teacher_password(struct node1*head, long id)
{
//根据工号找到教师在链表中的位置
struct node1*p=head->next;
if(p==NULL)
{
printf("无教师信息!\n");
return;
}
while(p!=NULL)
{
if((p->t).badge==id)
{
break;
}
p=p->next;
}
if(p==NULL)
{
printf("工号有误,查无此人!\n");
return;
}
//修改教师链表中的内容
//保存新密码
char password[15];
printf("请输入新密码:");
scanf("%s",password);
while(getchar()!='\n');
strcpy((p->t).password,password);
//修改教师文件内的内容
modify_teacher_password_file(id,password);
return;
}
4.添加学生(teacher功能2)
/*
函数功能:建立学生结点
函数参数:无
返回值:结点的地址
*/
struct node2* create_s_node()
{
struct node2 *pnew=NULL;
pnew=(struct node2*)malloc(sizeof(struct node2));
assert(pnew!=NULL);
pnew->next=NULL;
return pnew;
}
/*
函数功能:通过学号查找学生
函数参数:学生链表的头结点地址,搜索学号
返回值:int型数据
函数说明:(辅助学生信息添加函数)
若未找到返回0,若找到了返回1
*/
int search_s_info_id(struct node2 *head,long id)
{
struct node2 *p=head->next;//p指针指向第一个学生结点
if(head->next==NULL)//判断是否为空链表
{
return 0;
}
while(((p->stu).id)!=id)
{
p=p->next;
if(p==NULL)//如果遍历链表都未找到
{
return 0;//未找到
}
}
return 1;
}
/*
函数功能:输入学生的信息
函数参数:学生信息结构体地址,教师链表的头结点地址,学生链表的头结点地址
返回值:无
函数说明:只录入一个学生信息
*/
void input_student(Stu *s,struct node1 *head_t,struct node2 *head_s)
{
int ret1;//接收老师id查找返回值
int ret2;//接收学生id查找返回值
long id;//学号
char name[20];//姓名
char gender[4];//性别
char password[15];//密码
double Math,Chinese,English;//科目成绩
unsigned int year,month,day;//出生年月日
unsigned int DAY_p[12]={31,28,31,30,31,30,31,31,30,31,30,31};
unsigned int DAY_r[12]={31,29,31,30,31,30,31,31,30,31,30,31};
//学号重复判断
printf("请输入学生的学号:");
scanf("%ld",&id);
while(getchar()!='\n');
ret1=search_t_info_id(head_t,id);//教师链表查找
ret2=search_s_info_id(head_s,id);//学生链表查找
//printf("学号重复检测:\n");
//如果学号重复
while(ret1==1||ret2==1)
{
printf("学号重复,请重新输入:");
scanf("%ld",&id);
while(getchar()!='\n');
ret1=search_t_info_id(head_t,id);//重新查找
ret2=search_s_info_id(head_s,id);
}
//输入姓名
printf("请输入学生的姓名:");
scanf("%s",name);
while(getchar()!='\n');
//输入性别
printf("请输入学生的性别(男或女):");
scanf("%s",gender);
while(getchar()!='\n');
while(strcmp("男",gender)!=0&&strcmp("女",gender)!=0)
{
printf("性别有误,请重新输入性别:");
scanf("%s",gender);
while(getchar()!='\n');
}
//输入年
printf("请输入学生的生日的年份(1952-2023):");
scanf("%u",&year);
while(getchar()!='\n');
while(year>2023||year<1950)
{
printf("年份有误,请重新输入年份:");
scanf("%d",&year);
while(getchar()!='\n');
}
//输入月
printf("请输入学生的生日的月份(1-12):");
scanf("%u",&month);
while(getchar()!='\n');
while(month>12||month<1)
{
printf("月份有误,请重新输入月份:");
scanf("%u",&month);
while(getchar()!='\n');
}
//输入日
printf("请输入学生的生日的日(1-12):");
scanf("%u",&day);
while(getchar()!='\n');
//判断是否是闰年
if((year%4==0&&year%100!=0)||year%400==0)//是闰年
{
while(day>DAY_r[month-1]||day<1)
{
printf("日期有误,请重新输入日期:");
scanf("%u",&day);
while(getchar()!='\n');
}
}else//不是闰年
{
while(day>DAY_p[month-1]||day<1)
{
printf("日期有误,请重新输入日期:");
scanf("%u",&day);
while(getchar()!='\n');
}
}
//输入密码
printf("请输入学生的登陆密码(最高15字符):");
scanf("%s",password);
while(getchar()!='\n');
//输入成绩
//数学
printf("请输入学生的数学成绩:");
scanf("%lf",&Math);
while(getchar()!='\n');
while(Math>150||Math<0)
{
printf("成绩有误,请重新输入:");
scanf("%lf",&Math);
while(getchar()!='\n');
}
//语文
printf("请输入学生的语文成绩:");
scanf("%lf",&Chinese);
while(getchar()!='\n');
while(Chinese>150||Chinese<0)
{
printf("成绩有误,请重新输入:");
scanf("%lf",&Chinese);
while(getchar()!='\n');
}
//英语
printf("请输入学生的英语成绩:");
scanf("%lf",&English);
while(getchar()!='\n');
while(English>150||English<0)
{
printf("成绩有误,请重新输入:");
scanf("%lf",&English);
while(getchar()!='\n');
}
//将合法的数据输入教师信息的结构体
s->id=id;
strcpy(s->name,name);
strcpy(s->gender,gender);
(s->birth).year=year;
(s->birth).month=month;
(s->birth).day=day;
strcpy(s->password,password);
s->Math=Math;
s->Chinese=Chinese;
s->English=English;
return ;
}
/*
函数功能:将学生信息录入文件中
函数参数:学生信息结构体
返回值:布尔类型
函数说明:若是写入文件成功返回1,不成功返回0
*/
bool into_file_s(Stu s)
{
FILE *fp=NULL;
fp=fopen("student.txt","a");
assert(fp!=NULL);
int ret;
ret=fprintf(fp,"%ld %s %s %u-%u-%u %s %lf %lf %lf\n",s.id,s.name,s.gender,(s.birth).year,(s.birth).month,(s.birth).day,s.password,s.Math,s.Chinese,s.English);
if(ret>0)
{
fclose(fp);
return true;
}else
{
fclose(fp);
return false;
}
}
/*
函数功能:循环添加新学生
函数参数:教师链表的头结点地址,学生头结点地址(用于防止学号重复)
返回值:无
函数说明:使用尾插法实现结点的添加
*/
void add_student_link(struct node1 *head1,struct node2 *head2)
{
struct node2 *tail=NULL;
struct node2 *pnew=NULL;
int ret2;//接收文件录入返回值
char ch;//判断是否继续录入信息
//找到链表中的尾部
if(head2->next!=NULL)//如果链表不为空
{
tail=head2->next;//尾指针指向第一个结点
while(tail->next!=NULL)//尾指针的next不是空
{
tail=tail->next;//尾指针移动
}
}
//创造并用尾插法插入结点
while(1)
{
pnew=create_s_node();
//printf("创建结点成功!\n");//测试
input_student(&(pnew->stu),head1,head2);
printf("录入成功!\n");
ret2=into_file_s(pnew->stu);
if(ret2==0)//测试是否成功读入文件
{
printf("录入文件失败!\n");
break;
}
printf("录入文件成功!\n");
//如果是空链表
if(head2->next==NULL)
{
head2->next=pnew;
tail=pnew;
}else
{
tail->next=pnew;
tail=pnew;
}
printf("是否继续录入学生信息(y/n):");
scanf("%c",&ch);
while(getchar()!='\n');
if((ch!='y'||ch!='Y')&&(ch=='n'||ch=='N'))
{
break;
}
}
return;
}
5.删除学生(teacher功能3)
根据学号删除学生:
/*
函数功能:删除文件中的学生信息
函数参数:要删除的结点的位置
返回值:无
函数说明:建立另一个文件接收与欲删除数据不同的数据,
然后删除源文件重命名新文件
*/
void delete_file_student(struct node2*p)
{
FILE *fp=NULL,*ft=NULL;
int ret1;
Stu set;
fp=fopen("student.txt","rt+");
ft=fopen("temp3.txt","wt");
assert(fp!=NULL&&ft!=NULL);
while(1)
{
ret1=fscanf(fp,"%ld %s %s %u-%u-%u %s %lf %lf %lf\n",&(set.id),set.name,set.gender,&((set.birth).year),&((set.birth).month),&((set.birth).day),set.password,&(set.Math),&(set.Chinese),&(set.English));
if(ret1<=0)
{
break;
}
//printf("%ld %s %s %u-%u-%u\n",set.badge,set.name,set.gender,(set.birth).year,(set.birth).month,(set.birth).day);//测试
if((p->stu).id!=set.id)
{
fprintf(ft,"%ld %s %s %u-%u-%u %s %lf %lf %lf\n",set.id,set.name,set.gender,(set.birth).year,(set.birth).month,(set.birth).day,set.password,set.Math,set.Chinese,set.English);
}
}
rewind(fp);
fclose(fp);
fclose(ft);
remove("student.txt");
rename("temp3.txt","student.txt");
printf("文件删除成功!\n");//测试
return;
}
/*
函数功能:通过学号删除学生信息
函数参数:无
返回值:无
*/
void delete_student(struct node2 *head,long id)
{
//找到学号对应的结点地址
struct node2 *p=head->next;
if(head->next==NULL)//判断是否为空链表
{
printf("有误,无学生信息!\n");
return;
}
while(((p->stu).id)!=id)//如果未找到
{
head=head->next;
p=p->next;
if(p==NULL)//如果遍历链表都未找到
{
printf("学号错误!\n");
return;
}
}
head->next=p->next;
delete_file_student(p);
free(p);
printf("删除成功!\n");
return;
}
6.查询学生信息(teacher功能4)
根据学号查询学生信息:
/*
函数功能:查询学生信息并展示
函数参数:链表头结点地址,查询的学生id
返回值:
函数说明:使用链表查询(这就意味着数据是一次性的,要是想要链表里有数据,需要在每次打开程序的时候进行从文件中读取赋值)
注:虽然通过文件直接查询更保险,但是为了测试链表和文件信息的链结,建立此函数
*/
void seacher_student_id_link(struct node2*head,long id)
{
struct node2 *p=head->next;//p指针指向第一个学生结点
if(head->next==NULL)//判断是否为空链表
{
printf("学生信息库为空!\n");
return;
}
while(((p->stu).id)!=id)
{
p=p->next;
if(p==NULL)//如果遍历链表都未找到
{
printf("该学号不存在!\n");
return;
}
}
printf("学号:%ld 姓名:%s 性别:%s 出生日期:%u-%u-%u 登陆密码:%s 数学成绩:%1.1lf 语文成绩:%1.1lf 英语成绩:%1.1lf\n",(p->stu).id,(p->stu).name,(p->stu).gender,(p->stu).birth.year,(p->stu).birth.month,(p->stu).birth.day,(p->stu).password,(p->stu).Math,(p->stu).Chinese,(p->stu).English);
return;
}
6.修改学生信息(teacher功能5)
/*
函数功能:修改学生信息
函数参数:教师头结点地址,学生头结点地址,修改的工号
返回值:无
*/
void modify_student(struct node2*head_s,long id)
{
//找到学号对应的结点地址
struct node2 *p=head_s->next;
if(head_s->next==NULL)//判断是否为空链表
{
printf("有误,无学生信息!\n");
return;
}
while(((p->stu).id)!=id)//如果未找到
{
p=p->next;
if(p==NULL)//如果遍历链表都未找到
{
printf("学号错误!\n");
return;
}
}
//修改链表中的内容
char name[20];//姓名
char gender[4];//性别
char password[15];//密码
double Math,Chinese,English;//科目成绩
unsigned int year,month,day;//出生年月日
unsigned int DAY_p[12]={31,28,31,30,31,30,31,31,30,31,30,31};
unsigned int DAY_r[12]={31,29,31,30,31,30,31,31,30,31,30,31};
//输入姓名
printf("请输入学生的姓名:");
scanf("%s",name);
while(getchar()!='\n');
//输入性别
printf("请输入学生的性别(男或女):");
scanf("%s",gender);
while(getchar()!='\n');
while(strcmp("男",gender)!=0&&strcmp("女",gender)!=0)
{
printf("性别有误,请重新输入性别:");
scanf("%s",gender);
while(getchar()!='\n');
}
//输入年
printf("请输入学生的生日的年份(1952-2023):");
scanf("%u",&year);
while(getchar()!='\n');
while(year>2023||year<1950)
{
printf("年份有误,请重新输入年份:");
scanf("%d",&year);
while(getchar()!='\n');
}
//输入月
printf("请输入学生的生日的月份(1-12):");
scanf("%u",&month);
while(getchar()!='\n');
while(month>12||month<1)
{
printf("月份有误,请重新输入月份:");
scanf("%u",&month);
while(getchar()!='\n');
}
//输入日
printf("请输入学生的生日的日(1-12):");
scanf("%u",&day);
while(getchar()!='\n');
//判断是否是闰年
if((year%4==0&&year%100!=0)||year%400==0)//是闰年
{
while(day>DAY_r[month-1]||day<1)
{
printf("日期有误,请重新输入日期:");
scanf("%u",&day);
while(getchar()!='\n');
}
}else//不是闰年
{
while(day>DAY_p[month-1]||day<1)
{
printf("日期有误,请重新输入日期:");
scanf("%u",&day);
while(getchar()!='\n');
}
}
//输入密码
printf("请输入学生的登陆密码(最高15字符):");
scanf("%s",password);
while(getchar()!='\n');
//输入成绩
//数学
printf("请输入学生的数学成绩:");
scanf("%lf",&Math);
while(getchar()!='\n');
while(Math>150||Math<0)
{
printf("成绩有误,请重新输入:");
scanf("%lf",&Math);
while(getchar()!='\n');
}
//语文
printf("请输入学生的语文成绩:");
scanf("%lf",&Chinese);
while(getchar()!='\n');
while(Chinese>150||Chinese<0)
{
printf("成绩有误,请重新输入:");
scanf("%lf",&Chinese);
while(getchar()!='\n');
}
//英语
printf("请输入学生的英语成绩:");
scanf("%lf",&English);
while(getchar()!='\n');
while(English>150||English<0)
{
printf("成绩有误,请重新输入:");
scanf("%lf",&English);
while(getchar()!='\n');
}
//将合法的数据输入学生信息的结构体
strcpy((p->stu).name,name);
strcpy((p->stu).gender,gender);
((p->stu).birth).year=year;
((p->stu).birth).month=month;
((p->stu).birth).day=day;
strcpy((p->stu).password,password);
(p->stu).Math=Math;
(p->stu).Chinese=Chinese;
(p->stu).English=English;
//修改文件中的内容
FILE *fp=NULL,*ft=NULL;
int ret1;
Stu set;
fp=fopen("student.txt","rt+");
ft=fopen("temp4.txt","wt");
assert(fp!=NULL&&ft!=NULL);
while(1)
{
ret1=fscanf(fp,"%ld %s %s %u-%u-%u %s %lf %lf %lf\n",&(set.id),set.name,set.gender,&((set.birth).year),&((set.birth).month),&((set.birth).day),set.password,&(set.Math),&(set.Chinese),&(set.English));
if(ret1<=0)
{
break;
}
if((p->stu).id==set.id)
{
strcpy(set.name,name);
strcpy(set.gender,gender);
(set.birth).year=year;
(set.birth).month=month;
(set.birth).day=day;
strcpy(set.password,password);
set.Math=Math;
set.Chinese=Chinese;
set.English=English;
}
fprintf(ft,"%ld %s %s %u-%u-%u %s %lf %lf %lf\n",set.id,set.name,set.gender,(set.birth).year,(set.birth).month,(set.birth).day,set.password,set.Math,set.Chinese,set.English);
}
rewind(fp);
fclose(fp);
fclose(ft);
remove("student.txt");
rename("temp4.txt","student.txt");
//printf("文件删除成功!\n");//测试
printf("修改成功!\n");
return;
}
7.显示学生信息(teacher功能6)
包含多种显示的方式:
/*
函数功能:显示学生信息
函数参数:无
返回值:无
函数说明:打开文件读取数据,**********测试函数
*/
void show_student()
{
FILE *fp=NULL;
int ret;
Stu s;
fp=fopen("student.txt","r");
assert(fp!=NULL);
printf("学号 姓名 性别 出生日期 登陆密码 数学成绩 语文成绩 英语成绩\n");
while(1)
{
ret=fscanf(fp,"%ld %s %s %u-%u-%u %s %lf %lf %lf\n",&(s.id),s.name,s.gender,&((s.birth).year),&((s.birth).month),&((s.birth).day),s.password,&(s.Math),&(s.Chinese),&(s.English));
if(ret<=0)
{
break;
}
printf("%ld %s %s %u-%u-%u %s %lf %lf %lf\n",s.id,s.name,s.gender,(s.birth).year,(s.birth).month,(s.birth).day,s.password,s.Math,s.Chinese,s.English);
}
fclose(fp);
return;
}
/*
函数功能:1)按学号从低到高查看所有学生信息
函数参数:学生头结点地址
返回值:最大值结点的地址
函数说明:找最大学号节点
*/
struct node2*s_max_id(struct node2*head_s)
{
struct node2*p=head_s->next;
struct node2*pmax=head_s->next;
while(p!=NULL)
{
if((pmax->stu).id<(p->stu).id)
{
pmax=p;
}
p=p->next;
}
return pmax;
}
/*
函数功能:2)从链表中删除节点
函数参数:学生头结点地址,最大值结点地址
返回值:无
*/
void delete_max(struct node2*head_s,struct node2*pmax)
{
struct node2*p=head_s;
while(p->next!=pmax)
{
p=p->next;
}
p->next=pmax->next;
pmax->next=NULL;
return ;
}
/*
函数功能:3)创建新的链表
函数参数:学生头结点地址,最大值结点地址
返回值:无
*/
void create_newlink(struct node2*new_head,struct node2*pmax)
{
pmax->next=new_head->next;
new_head->next=pmax;
return ;
}
/*
函数功能:4)对学生链表排序
函数参数:学生链表的头结点地址
返回值:新头结点地址
*/
struct node2* show_by_id(struct node2*head_s)
{
struct node2 *new_head=NULL;
new_head=create_s_node();
struct node2 *pmax=NULL;
while(head_s->next!=NULL)
{
//找最大学号
pmax=s_max_id(head_s);
//删除
delete_max(head_s,pmax);
//创建
create_newlink(new_head,pmax);
}
free(head_s);
return new_head;
}
//按数学成绩从高到低查看所有学生信息
struct node2* show_by_math(struct node2*head_s)
{
struct node2 *new_head=NULL;
new_head=create_s_node();
while(head_s->next!=NULL)
{
struct node2*pmin=head_s->next;
struct node2*p=head_s->next;
//找最小成绩
while(p!=NULL)
{
if((pmin->stu).Math > (p->stu).Math)
{
pmin=p;
}
p=p->next;
}
//删除
delete_max(head_s,pmin);
//创建
create_newlink(new_head,pmin);
}
free(head_s);
return new_head;
}
//按语文成绩从高到低查看所有学生信息
struct node2* show_by_Chinese(struct node2*head_s)
{
struct node2 *new_head=NULL;
new_head=create_s_node();
while(head_s->next!=NULL)
{
struct node2*pmin=head_s->next;
struct node2*p=head_s->next;
//找最小成绩
while(p!=NULL)
{
if((pmin->stu).Chinese > (p->stu).Chinese)
{
pmin=p;
}
p=p->next;
}
//删除
delete_max(head_s,pmin);
//创建
create_newlink(new_head,pmin);
}
free(head_s);
return new_head;
}
//按英语成绩从高到低查看所有学生信息
struct node2* show_by_English(struct node2*head_s)
{
struct node2 *new_head=NULL;
new_head=create_s_node();
while(head_s->next!=NULL)
{
struct node2*pmin=head_s->next;
struct node2*p=head_s->next;
//找最小成绩
while(p!=NULL)
{
if((pmin->stu).English> (p->stu).English)
{
pmin=p;
}
p=p->next;
}
//删除
delete_max(head_s,pmin);
//创建
create_newlink(new_head,pmin);
}
free(head_s);
return new_head;
}
//按总分从高到低查看所有学生信息
struct node2* show_by_sum(struct node2*head_s)
{
struct node2 *new_head=NULL;
new_head=create_s_node();
while(head_s->next!=NULL)
{
struct node2*pmin=head_s->next;
struct node2*p=head_s->next;
//找最小成绩
while(p!=NULL)
{
if(((pmin->stu).Math+(pmin->stu).Chinese+(pmin->stu).English) > ((p->stu).Chinese+(p->stu).Math+(p->stu).English))
{
pmin=p;
}
p=p->next;
}
//删除
delete_max(head_s,pmin);
//创建
create_newlink(new_head,pmin);
}
free(head_s);
return new_head;
}
/*
函数功能:显示学生链表内容
函数参数:学生链表的头结点地址
返回值:无
*/
void show_student_link(struct node2*head_s)
{
struct node2*p=head_s->next;
if(p==NULL)
{
printf("无学生信息!\n");
return;
}
printf("学号\t姓名\t性别\t出生日期 登陆密码 数学成绩 语文成绩 英语成绩\n");
while(p!=NULL)
{
printf("%ld\t%s\t%s\t%u-%u-%u %s %1.1lf %1.1lf %1.1lf\n",(p->stu).id,(p->stu).name,(p->stu).gender,((p->stu).birth).year,((p->stu).birth).month,((p->stu).birth).day,(p->stu).password,(p->stu).Math,(p->stu).Chinese,(p->stu).English);
p=p->next;
}
return;
}
总结
这个代码写的也比较啰嗦,代码不追求简洁,只求达到功能,重于巩固自己所学。
这里同样存在更简洁的思路:若是更改了链表的内容,文件用“w”打开,写入链表中的内容即可。这里可以做一个函数模块,在使用时调用就可以了。