C语言学生管理系统(文件、链表)-(2)教师


前言


续上一个文章,头文件主函数在上一个文章中。
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”打开,写入链表中的内容即可。这里可以做一个函数模块,在使用时调用就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值