admin 管理员组文章数量: 887017
前言:
基本信息:
登录信息文件(自定义):
学生信息文件(自定义):
“系统构思”:
学生信息链表:
课程信息链表:
运行截图和基本函数:
初始化账户:
用户登录界面:
根据学号查找学生:
根据名称查找学生:
导入学生信息:
导出学生信息:
管理员删除页面:
按学号删除学生:
释放所有动态内存:
查询某班级某门课程排名情况(自行转换瑕疵):
展示所有学生信息:
展示某个同学信息:
管理员添加学生信息:
是否确认修改:
改变学生信息:
课程信息更改:
源码:
前言:
源码置于文末,原创,取用不忘点赞,不符之处请读者根据要求自行更改!
基本信息:
登录信息文件(自定义):
学生信息文件(自定义):
“系统构思”:
学生信息链表:
课程信息链表:
运行截图和基本函数:
初始化账户:
void initaccountes(Loggers* q){
FILE *fp=fopen(Infileaccount,"r");//以只读的方式打开登录信息文本文件,文件必须存在
if(!fp){printf("用户登陆信息文件打开失败!\n");exit(2);}//文件打开失败提醒
(*q)->next=NULL;//为登录信息链表头插法做准备
Loggers current=(Loggers)malloc(sizeof(loggers));//申请登录信息节点
if(!current){printf("初始化账户内存不够!\n");exit(3);}//申请失败提醒
printf("登录账号\t密码 身份\n");
while(fscanf(fp,"%s%s%d",current->account,current->password,¤t->users)==3)//按条件读取文件账号、密码以及身份
{
printf("%s\t%s\t%d\n",current->account,current->password,current->users);
current->next=(*q)->next;
(*q)->next=current;//头插法
if(!(current=(Loggers)malloc(sizeof(loggers)))){
printf("初始化账户内存不够!\n");exit(3);}//为下一次读取信息做准备
}
printf("用户登陆信息显示成功!\n用户登陆信息文件%s内容读取成功!\n",Infileaccount);
fclose(fp);//关闭文件
}
用户登录界面:
void tablelog(Loggers q,Students qq){
initaccountes(&q);//调用函数初始化账户信息
shower(qq);//展示所有输入的学生信息
printf(" _____________________________________\n");
printf("| 欢迎来到学生管理系统 |\n");
printf("|_____________________________________|\n");
char account1[15],password1[15];//登陆时输入的账号以及密码
Loggers p,r;
int opportunity=Attemptingpassword,user,key=1;//key的值的改变判断登录成功与否
while(key)
{
printf("请依次正确输入您的账号,密码和用户类型(123456 abcdef 1普通用户/0管理员):");
while(fflush(stdin),scanf("%s%s%d",account1,password1,&user)!=3||user<0||user>1) printf("请输入正确数据格式以及状态(0/1):");//fflush(stdin)清空输入缓冲区,循环条件的满足为fflush(stdin)其后的','表达式后面的表达式是否为真
p=r=q;
while(p=p->next)//第一个正确登陆数据节点是否存在并在其后不断循环
if(!strcmp(account1,p->account)&&!(strcmp(password1,p->password)))//账号密码同时成立
if(user)
{
printf("普通用户账号登陆成功!\n");
key=0;//最外层循环条件不满足,表示登陆成功
norsearch(qq);//进入普通用户界面
freeall(&qq,&q);//释放所有账户以及学生信息
break;//终止用户登录验证界面(已经登陆成功)
}
else
{
printf("管理员账号登陆成功!\n");
key=0;
DeleteTable(&qq);//进入管理员操作页面
impartstuinfo(qq);//保存管理员操作后的信息
freeall(&qq,&q);
break;
}
if(!p)//登陆失败时查找失败原因(账号/密码/账号和密码)错误
{
r=q;//为头节点的下一届节点做准备
if(--opportunity)//登陆机会减少1次后还有无机会(非零还有机会)
{
while(r=r->next)
{
if(!strcmp(account1,r->account))//账号正确
{
printf("密码错误!您还有%d次有效机会!\n",opportunity);break;//错误原因查找成功
}
else if(!strcmp(password1,r->password))//密码正确
{
printf("账号错误!您还有%d次有效机会!\n",opportunity);break;
}
}
if(!r) //账号密码均不正确时访问至空节点
printf("账号密码错误!您还有%d次有效机会!\n", opportunity);
}
else//opportunity为0时无剩余机会
{
printf("很抱歉,机会已耗尽,您的账户已被锁定,请稍后尝试\n",opportunity);
freeall(&qq,&q);
exit(1);//登陆失败程序异常终止提醒
}
}
}
}
根据学号查找学生:
Students searchnumber(Students pre)
{
printf("请输入您想要查询的学生学号(12345678901):");
char number[15];
Students now=pre;
while(fflush(stdin),scanf("%s",number)!=1) printf("请输入正确学号(12345678901):");//清空输入缓冲区并检测是否满足输入条件
while(now)
{
if(!strcmp(now->number,number))//学号查找成功
{
showerone(now);//展示查找到的学生的信息
return now;
}
else if(!(now->next))//查找至最后一个节点的空指针域
{
printf("无学号为%s的学生!\n",number);
return NULL;
}
now=now->next;
}
}
根据名称查找学生:
Students searchname(Students pre,char*name,int num)
{
int number=num;//是否重名以及是否存在此名称学生
Students now=pre;
while(now)//学生节点存在即循环
{
if(!strcmp(now->name,name))//名称相匹配
{
showerone(now);//展示此学生信息
//printf("%d:学生%s查询成功!\n",++number,now->number,now->name);//show(now);
searchname(now->next,name,++number);//继续循环直至无学生信息节点
return now;//返回查找到的当前节点
}
else if(!(now->next)&&!number)//找至最后一个节点的空指针域以及number==0时为查找失败
{
printf("无名称为%s的学生!\n",name);
return NULL;
}
now=now->next;//下一个学生节点
}
}
导入学生信息:
Students stuinfoget()
{
FILE *fp=fopen(Infilestu,"r");//以只读的方式打开文本文件,文件必须存在
if(!fp){printf("文件%s打开失败,学生信息读取失败!\n",Infilestu);exit(1);}//文件读入失败时退出程序
Students current,previous=NULL,origin;
Curriculums now,pre=NULL;
char c=' ';//方便(c=='#')||((c=fgetc(fp))=='#')的正确执行 (如果是'#'而且没有到达文件尾直接进入循环,否则读取一个文件字符再进行循环)
while(!feof(fp))//未到文件尾时继续循环
{
while(((c=='#')||((c=fgetc(fp))=='#'))&&c!=EOF)//先判断'#',是则判断是否不为EOF,否则读取一个文件后再判断EOF,如果刚开始以及读取一个后都不为'#',则退出此循环
{
if(!(current=(Students)malloc(sizeof(students)))){printf("内存不足,申请学生信息失败!\n");exit(1);}//申请内存信息失败时退出程序
if(fscanf(fp,"%s%s%s%s",current->banji,current->name,current->number,current->gender)==4)//成功读入学生基本信息
{
current->next=current->pre=NULL;//置空当前指针信息
if(!previous) origin=current;//previous为空,此时为第一个节点,用origin保存
if(!(now=current->curriculum=malloc(sizeof(curriculums)))){
printf("内存不足,申请学生%s课程信息失败!\n",current->name);exit(2);}//申请此学生的第一个课程信息以及相应的判断
if(fscanf(fp,"%s%s%f",now->curriculum,now->semester,&now->score)==3)
now->next=now->pre=NULL;//初始化第一个课程节点的指针域
pre=now;//方便下一个课程节点的插入
while((c=fgetc(fp))=='$')//从第二个开始进行课程信息循环,退出时c要么为 '#',要么为EOF
{
if(!(now=malloc(sizeof(curriculums)))){
printf("内存不足,申请学生%s课程信息失败!\n",current->name);exit(3);}//申请以及判断
if(fscanf(fp,"%s%s%f",now->curriculum,now->semester,&now->score)==3)//成功读入课程信息
{
now->next=pre->next;//当前课程节点的后继为前一个节点的后继
now->pre=pre;//当前课程节点的前继为前一个结点
pre->next=now;//前一个课程节点的后继为当前课程节点
}
pre=now;//当前课程节点赋给前一个课程节点
}
}
if(previous)//如果学生信息节点不唯一,进行类似的插入操作
{
current->next=previous->next;
current->pre=previous;
previous->next=current;
}
previous=current;//当前学生节点赋值给前一个学生节点
}
}
fclose(fp);//关闭打开文件
printf("学生信息读取成功!\n");
return origin;
}
导出学生信息:
void impartstuinfo(Students q)
{
FILE *fp=fopen(Outfilestu,"w");//w:以只写的方式打开文本文件,文件若存在则清空文件内容从文件头部开始写,若不存在则根据文件名创建新文件并只写打开
if(!fp){printf("写入文件%s打开失败!\n",Outfilestu);exit(1);}//打开失败,程序退出
Students current=q;Curriculums now;
while(current)//学生信息节点存在时
{
if(strcmp(current->name,""))//如果为真,则为已经删除的第一个节点以及后继节点组成,此时跳过第一个节点
{
now=current->curriculum;
fprintf(fp,"#%s %s %s %s %s %s %.2f",current->banji,current->name,current->number,current->gender,now->curriculum,now->semester,now->score);//此方式方便打开文件的操作
while(now=now->next)//第二个课程节点以及其后存在时
fprintf(fp,"$ %s %s %.2f",now->curriculum,now->semester,now->score);
fputc('\n',fp);//输出换行符至已打开文件
}
current=current->next;//下一个学生信息节点
}
fclose(fp);//关闭写入完毕的文件
printf("学生信息写入文件%s成功!\n",Outfilestu);
}
管理员删除页面:
void DeleteTable(Students* origin)
{
Students now;
int todo;
char number[15],name[10];
while(1)//不断循环
{
printf("请输入您想要进行的操作:1.按学号删除学生\t2.按名称查询学生\t3.按学号查询学生\t4.添加学生信息\t5.按学号修改学生信息\t6.退出(1/2/3/4/5/6):");
while(fflush(stdin),scanf("%d",&todo)!=1||todo<1||todo>6) printf("请输入有效选项(1-6):");//清空输入缓冲区并检验输入是否符合(是否进入循环)
switch(todo)
{
case 1:if(!(now=searchnumber(*origin))) break;//如果学号同学不存在则结束此轮选择
deletesthroughnumber(&now);break;//否则调用函数删除/修改(第一个节点)节点信息后结束此轮选择
case 2:printf("请输入待查找的名称(重庆):");
while(fflush(stdin),scanf("%s",name)!=1) ;
searchname(*origin,name,0);break;//0不断在函数内更新以检验有无以及是否多个同名学生
case 3:searchnumber(*origin);break;//调用函数
case 4:anew(origin);break;//调用添加函数
case 5:if(!(now=searchnumber(*origin))) break;
changeable(&now);break;
case 6:return;//退出当前函数,返回上一级
default:;
}
}
}
按学号删除学生:
void deletesthroughnumber(Students* origin)
{
if(!*origin) exit(1);//*origin为空时,程序退出
if(!(*origin)->next&&!(*origin)->pre) exit(1);//*origin唯一时,程序退出
else if(!(*origin)->next)//由上一条if语句易知此时当前节点的两个指针域至少有一个不为空,此时节点空后,*origin为尾节点时,置空前一个节点的后指针域,并在最后统一释放内存
(*origin)->pre->next=NULL;
else if(!(*origin)->pre)//此时节点空前,*origin为第一个节点,由于没有头节点,故仅将此节点所有信息置为空,第一个成绩数据记为负数(方便清空整个学生链表)
{
Curriculums previous,current=(*origin)->curriculum;
strcpy((*origin)->banji,"");
strcpy((*origin)->name,"");
strcpy((*origin)->number,"");
strcpy((*origin)->gender,"");
strcpy(current->semester,"");
strcpy(current->curriculum,"");
current->score=Fault;
while(current=current->next)//从第二个课程节点开始删除
{
previous=current;
current=current->next;
free(previous);
}
(*origin)->curriculum->next=NULL;
printf("删除成功!\n");
return;//避免第一个节点被删除后结束时无法删除其后的节点
}
else//当前节点的两个指针域都存在时的删除操作
{
(*origin)->pre->next=(*origin)->next;
(*origin)->next->pre=(*origin)->pre;
}
free(*origin);//统一删除可以删除的节点
printf("删除成功!\n");
}
释放所有动态内存:
void freeall(Students* origin,Loggers* key)
{
if(*origin)//第一个学生信息节点存在时
{
Students current=*origin,previous;
Curriculums now,pre;
while(current)//学生信息节点存在时
{
now=current->curriculum;//当前学生的课程信息节点
while(now)//课程信息节点不为空时
{
pre=now;//当前课程节点
now=now->next;//下一个课程节点
free(pre);//释放当前课程节点
}
previous=current;//当前学咸亨信息节点
current=current->next;//下一个学生信息节点
free(previous);//适当当前学生信息节点
}
}
Loggers p=*key,q;
while(q=p,p=p->next)//有头节点的链表删除操作:q保留当前,p表示当前的指针域,若p不为空,释放当前节点
free(q);
free(q);//释放循环条件假时的最后一个节点
printf("数据释放成功!\n");
}
查询某班级某门课程排名情况(自行转换瑕疵):
void searchclasscurriculumrank(Students origin){
char banji[10],curriculum[20];
int i=0,j,k,num;
Students now=origin,primitive=origin;
Curriculums current;
ones a;//直接插入法的临时变量
Ones newone,previous=NULL,initial=NULL;
printf("请输入班级和课程(计算机217 高数):");
while(fflush(stdin),scanf("%s%s",banji,curriculum)!=2) printf("请输入有效信息:");
while(now)//学生信息存在
{
if(!strcmp(now->banji,banji))//班级符合
{
current=now->curriculum;
while(current)//课程信息存在
{
if(!strcmp(current->curriculum,curriculum))//课程符合
{
++i;break;//增加此班级课程人数
}
current=current->next;
}
}
now=now->next;
}
if(!i)//无待查找量
{
printf("无此课程或班级!\n");
exit(1);
}
if(!(initial=newone=(Ones)malloc(sizeof(ones)*(num=i))))//利用initial存储首地址,方便对已申请查找到的个数利用指针进行转数组进行排序
{printf("申请信息失败!\n");exit(1);}
while(primitive)//将目标值(班级、学号和这门课程的分数)带入新申请的空间中
{
if(!strcmp(primitive->banji,banji))
{
current=primitive->curriculum;
while(current)
{
if(!(strcmp(current->curriculum,curriculum)))
{
newone->score=current->score;
strcpy(newone->number,primitive->number);
strcpy((newone++)->name,primitive->name);//此次赋值操作后,newone指向申请的连续空间的下一个地址
}
current=current->next;
}
}
primitive=primitive->next;
}
previous=newone=initial;//回到首地址
for(i=1;i<num;++i)//直接插入法排序
{
a=previous[i];
j=i-1;
while(j>=0&&previous[j].score<a.score)
{
previous[j+1]=previous[j];
--j;
}
previous[j+1]=a;
}
for(i=0;i<num;++i)
printf("%d--%s--%s:%.2f\n",i+1,previous[i].number,previous[i].name,previous[i].score);
printf("成绩输出成功!\n");
}
展示所有学生信息:
void shower(Students origin)
{
Students current=origin;
Curriculums now;
printf("班级\t 名称\t学号\t性别课程-学期-成绩\n");
while(current)//学生信息节点存在时
{
now=current->curriculum;//当前学生信息节点中的第一个课程节点
printf("%s---%s---%s---%s-%s-%s-%.2f\t",current->banji,current->name,current->number,current->gender,now->curriculum,now->semester,now->score);
while(now=now->next)//第二个以及以后的课程节点存在时
printf("%s-%s-%.2f\t",now->curriculum,now->semester,now->score);
printf("\n");//每个同学信息输出完毕时换行
current=current->next;//下一个学生信息节点
}
printf("数据输出成功!\n");
}
展示某个同学信息:
void showerone(Students origin)
{
Students current=origin;
Curriculums now;
printf("班级\t 名称\t学号\t性别课程-学期-成绩\n");
now=current->curriculum;//当前学生信息中第一个课程信息节点
printf("%s---%s---%s---%s-%s-%s-%.2f\t",current->banji,current->name,current->number,current->gender,now->curriculum,now->semester,now->score);
while(now=now->next)//第二个以及以后的课程信息存在时
printf("%s-%s-%.2f\t",now->curriculum,now->semester,now->score);
printf("\n");
}
管理员添加学生信息:
void anew(Students* origin)
{
Students now=(Students)malloc(sizeof(students)),forever=*origin;
if(!now){printf("申请学生节点失败!\n");exit(1);}
char banji[10],name[10],number[15],gender;
Curriculums previous,curriculum;
int i=1;
while(i)//判断新增加学号是否符合唯一性规则
{
printf("请输入学号:");
while(fflush(stdin),scanf("%s",now->number)!=1) printf("请输入有效信息:");
while(forever)
{
if(!strcmp(now->number,forever->number))
{
printf("学号应具有唯一性!\n");
break;
}
else if(!(forever->next)) i=0;
forever=forever->next;
}
}
printf("请输入姓名:");
while(fflush(stdin),scanf("%s",now->name)!=1) printf("请输入有效信息:");
printf("请输入性别(f/m/F/M):");
while(((gender=getche())!='f')&&(gender!='M')&&(gender!='m')&&(gender!='F')){printf("\n请输入有效选项(f/F/m/M):");continue;}
printf("\n你输入的是%c\n",gender);
(gender=='f'||gender=='F')?strcpy(now->gender,"女"):strcpy(now->gender,"男");
printf("请输入班级:");
while(fflush(stdin),scanf("%s",now->banji)!=1) printf("请输入有效信息:");
now->next=(*origin)->next;//将学生信息利用头插法添加到双向链表中
now->pre=(*origin);
(*origin)->next=now;
printf("请输入学生课程信息(高数 大一 66.6):");
if(!(curriculum=now->curriculum=(Curriculums)malloc(sizeof(curriculums))))
{printf("请求课程信息失败!\n");exit(1);}
curriculum->next=curriculum->pre=NULL;//置空课程信息
fflush(stdin);//清空输入缓冲区
scanf("%s%s%f",curriculum->curriculum,curriculum->semester,&curriculum->score);
previous=curriculum;
if(!(curriculum=(Curriculums)malloc(sizeof(curriculums))))
{printf("请求课程信息失败!\n");exit(1);}
printf("请输入下一门课程信息(分数<=0结束):");
while(1)//不断添加课程信息
{
while(fflush(stdin),(scanf("%s%s%f",curriculum->curriculum,curriculum->semester,&curriculum->score)==3))
{
if(curriculum->score<=0)
{
free(curriculum);//释放此节点并等待返回
return;
}
curriculum->next=previous->next;//满足课程节点基本信息则头插法添加课程双向链表
curriculum->pre=previous;
previous->next=curriculum;
if(!(curriculum=(Curriculums)malloc(sizeof(curriculums)))){
printf("请求课程信息失败!\n");exit(1);}
printf("请输入下一门课程信息(分数<=0结束):");
}
}printf("学生%s信息添加成功!\n",now->name);
}
是否确认修改:
int Deliberation(){
printf("您确定修改此信息吗(y/Y/n/N)?");
char ch;
while(((ch=getche())!='y')&&(ch!='Y')&&(ch!='n')&&(ch!='N'))
{printf("\n请输入有效选项(y/Y/n/N):");continue;}//输入的非需要的字符,自动等待重新输入
printf("\n你输入的是%c\n",ch);
if(ch=='y'||ch=='Y') printf("此数据修改成功!\n");
else printf("抱歉,数据修改失败!\n");
return((ch=='y'||ch=='Y')?1:0);//确认返回值为真,否则为假
}
改变学生信息:
void changeable(Students* origin)
{
char banji[10],name[10];
int todo;
while(1)//不断循环
{
printf("请输入您想要修改的序号:\n1.姓名\t2.班级\t3.成绩信息\t4.返回:");
while(fflush(stdin),scanf("%d",&todo)!=1||todo<1||todo>4) printf("请输入有效选项(1-4):");//先清空输入缓冲区再读取数据
switch(todo)
{
case 1:printf("请输入修改后的姓名:");
while(fflush(stdin),scanf("%s",name)!=1) printf("请输入有效信息:");
if(Deliberation()) strcpy((*origin)->name,name);break;
case 2:printf("请输入修改后的班级:");
while(fflush(stdin),scanf("%s",banji)!=1) printf("请输入有效信息:");
if(Deliberation()) strcpy((*origin)->banji,banji);break;
case 3:CurriculumChange(&(*origin)->curriculum);break;//调用课程信息更改函数
case 4:return;//返回上一级
default:;
}
}
}
课程信息更改:
void CurriculumChange(Curriculums*origin)
{
Curriculums now,newone;
int todo,surrounding;
while(1)
{
printf("请输入您想要进行的操作:1.添加课程\t2.更改课程\t3.返回:");
while(fflush(stdin),scanf("%d",&todo)!=1||todo<1||todo>3) printf("请输入有效选项(1-3):");
if(!(newone=(Curriculums)malloc(sizeof(curriculums))))
{printf("申请课程信息节点失败!\n");exit(1);}
surrounding=1;
switch(todo)
{
case 1:printf("请输入新添加的课程信息(高数 大一 79.5)分数<=0退出:");
now=*origin;
while(fflush(stdin),scanf("%s%s%f",newone->curriculum,newone->semester,&newone->score)==3)//先清空输入缓冲区再输入数据
{
if(newone->score<=0)
{
printf("课程成绩%.2f不符合要求,添加失败!\n",newone->score);
free(newone);//成绩有误,释放数据等待返回
break;//结束当前循环
}
while(now)
{
if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester)&&now->score==newone->score)
{
printf("此同学%s时期%s课程分数%.2f添加前存在,添加失败!\n",now->semester,now->curriculum,now->score);
free(newone);//已存在输入数据,删除新添加的节点即可
surrounding=0;
break;//返回上一级
}
else if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester))
{
now->score=newone->score;//补充成绩即可
free(newone);//删除新添加项目即可
surrounding=0;
break;//返回上一级
}
now=now->next;
}
if(surrounding)
{
newone->next=(*origin)->next;
newone->pre=(*origin);
(*origin)->next=newone;
printf("%s-%s-%.2f添加成功!\n",newone->curriculum,newone->semester,newone->score);
}
if(!(newone=(Curriculums)malloc(sizeof(curriculums))))
{printf("申请课程信息节点失败!\n");exit(1);}
printf("请输入新添加的课程信息(高数 大一 79.5)分数<=0退出:");
}
break;
case 2:printf("请输入更改后的课程信息(高数 大一 79.5):");
now=*origin;
while(fflush(stdin),scanf("%s%s%f",newone->curriculum,newone->semester,&newone->score)==3)
{
if(newone->score<=0)
{
free(newone);//成绩有误,释放数据等待返回
printf("更改后的课程信息不符合要求,更改失败!\n");
break;//结束当前循环
}
while(now)
{
if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester)&&now->score==newone->score)
{
printf("此同学%s时期%s课程分数%.2f已存在!\n",now->semester,now->curriculum,now->score);
free(newone);//已存在输入数据,删除新添加的节点即可
surrounding=0;
break;//返回上一级
}
else if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester))
{
now->score=newone->score;//补充成绩即可
printf("更改成功!\n");
free(newone);//删除新添加项目即可
surrounding=0;
break;//返回上一级
}
else if(!strcmp(now->curriculum,newone->curriculum))
{
strcpy(now->semester,newone->semester);
now->score==newone->score;
printf("此同学%s时期%s课程分数%.2f更改成功!\n",now->semester,now->curriculum,now->score);
surrounding=0;
break;
}
now=now->next;
}
if(surrounding) printf("无相应的课程和时期,更改失败!\n");//无相应的课程以及学期
break;
}
break;
case 3:return;
default:;
}
}
}
源码:
#include<stdio.h>
#include<conio.h>//调用函数getche()
#include<stdlib.h>//调用函数malloc()和free()
#include<string.h>//调用函数strcpy()和strcmp()
#define Fault -100//由于第一个学生节点存储有学生信息,因此删除第一个学生节点信息时应完全改变其节点信息,用Fault来主要表示第一个学生节点存在与否
#define Attemptingpassword 3//登录信息最多尝试次数
#define Infileaccount "account.txt"//管理员以及学生登录时的账号读取文件
#define Infilestu "Importing.txt"//输入输出学生信息文件
#define Outfilestu "Importing.txt"
typedef struct curriculums
{
char curriculum[20],semester[20];//课程以及相应的学期
float score;//课程分数
struct curriculums *next,*pre;//课程节点为双向链表
}curriculums,*Curriculums;
typedef struct students
{
char banji[10],name[10],number[15],gender[3];//学生基本信息:班级、名称、学号(唯一)以及性别
Curriculums curriculum;//课程指针
struct students *next,*pre;//学生节点为双向链表
}students,*Students;
typedef struct loggers
{
int users;//enum users{adm,nor}users;//区别管理员0与普通用户 1
char account[15],password[15];//账号以及密码
struct loggers *next;//账户链表为单向链表
}loggers,*Loggers;
typedef struct one
{
char name[10],number[15];
float score;
}ones,*Ones;//班级课程排名辅助
void initaccount(Loggers*); //初始化账号、密码和状态的链表
void tablelog(Loggers,Students);//用户登录界面,鉴定有效次数以内用户是否登陆成功
Students searchnumber(Students);//根据唯一学号寻找学生,并返回相应的节点
Students searchname(Students,char*,int);//根据名称寻找学生,并用递归记载找到名称个数,达到输出重名学生的目的
Students stuinfoget();//初始化并返回学生信息的双向链表第一个节点
void impartstuinfo(Students);//管理员身份登陆退出后自动保存修改后的学生信息
void DeleteTable(Students*);//管理员操作界面
void deletesthroughnumber(Students*);//通过学号删除学生
void freeall(Students*,Loggers*);//释放学生信息和账户登录信息两种双向链表
void searchclasscurriculumrank(Students);//寻找某班某课程的排名情况
void shower(Students);//展示所有学生信息
void showerone(Students);//展示某一个存在的学生信息
void anew(Students*);//管理员新添加学生信息
int Deliberation();//是否确认修改
void changeable(Students*);//改变学生信息
void CurriculumChange(Curriculums*);//更换课程信息
float TemporaryScore;//用于班级课程排名
int main()
{
Loggers logger1=(Loggers)malloc(sizeof(loggers));
if(!logger1){
printf("申请登录信息以及学生信息失败!\n");exit(1);}
tablelog(logger1,stuinfoget());
return 0;
}
void CurriculumChange(Curriculums*origin)
{
Curriculums now,newone;
int todo,surrounding;
while(1)
{
printf("请输入您想要进行的操作:1.添加课程\t2.更改课程\t3.返回:");
while(fflush(stdin),scanf("%d",&todo)!=1||todo<1||todo>3) printf("请输入有效选项(1-3):");
if(!(newone=(Curriculums)malloc(sizeof(curriculums))))
{printf("申请课程信息节点失败!\n");exit(1);}
surrounding=1;
switch(todo)
{
case 1:printf("请输入新添加的课程信息(高数 大一 79.5)分数<=0退出:");
now=*origin;
while(fflush(stdin),scanf("%s%s%f",newone->curriculum,newone->semester,&newone->score)==3)
{
if(newone->score<=0)
{
printf("课程成绩%.2f不符合要求,添加失败!\n",newone->score);
free(newone);
break;
}
while(now)
{
if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester)&&now->score==newone->score)
{
printf("此同学%s时期%s课程分数%.2f添加前存在,添加失败!\n",now->semester,now->curriculum,now->score);
free(newone);
surrounding=0;
break;
}
else if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester))
{
now->score=newone->score;
free(newone);
surrounding=0;
break;
}
now=now->next;
}
if(surrounding)
{
newone->next=(*origin)->next;
newone->pre=(*origin);
(*origin)->next=newone;
printf("%s-%s-%.2f添加成功!\n",newone->curriculum,newone->semester,newone->score);
}
if(!(newone=(Curriculums)malloc(sizeof(curriculums))))
{printf("申请课程信息节点失败!\n");exit(1);}
printf("请输入新添加的课程信息(高数 大一 79.5)分数<=0退出:");
}
break;
case 2:printf("请输入更改后的课程信息(高数 大一 79.5):");
now=*origin;
while(fflush(stdin),scanf("%s%s%f",newone->curriculum,newone->semester,&newone->score)==3)
{
if(newone->score<=0)
{
free(newone);
printf("更改后的课程信息不符合要求,更改失败!\n");
break;
}
while(now)
{
if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester)&&now->score==newone->score)
{
printf("此同学%s时期%s课程分数%.2f已存在!\n",now->semester,now->curriculum,now->score);
free(newone);
surrounding=0;
break;
}
else if(!strcmp(now->curriculum,newone->curriculum)&&!strcmp(now->semester,newone->semester))
{
now->score=newone->score;
printf("更改成功!\n");
free(newone);
surrounding=0;
break;
}
else if(!strcmp(now->curriculum,newone->curriculum))
{
strcpy(now->semester,newone->semester);
now->score==newone->score;
printf("此同学%s时期%s课程分数%.2f更改成功!\n",now->semester,now->curriculum,now->score);
surrounding=0;
break;
}
now=now->next;
}
if(surrounding) printf("无相应的课程和时期,更改失败!\n");
break;
}
break;
case 3:return;
default:;
}
}
}
int Deliberation(){
printf("您确定修改此信息吗(y/Y/n/N)?");
char ch;
while(((ch=getche())!='y')&&(ch!='Y')&&(ch!='n')&&(ch!='N'))
{printf("\n请输入有效选项(y/Y/n/N):");continue;}
printf("\n你输入的是%c\n",ch);
if(ch=='y'||ch=='Y') printf("此数据修改成功!\n");
else printf("抱歉,数据修改失败!\n");
return((ch=='y'||ch=='Y')?1:0);
}
void changeable(Students* origin)
{
char banji[10],name[10];
int todo;
while(1)
{
printf("请输入您想要修改的序号:\n1.姓名\t2.班级\t3.成绩信息\t4.返回:");
while(fflush(stdin),scanf("%d",&todo)!=1||todo<1||todo>4) printf("请输入有效选项(1-4):");
switch(todo)
{
case 1:printf("请输入修改后的姓名:");
while(fflush(stdin),scanf("%s",name)!=1) printf("请输入有效信息:");
if(Deliberation()) strcpy((*origin)->name,name);break;
case 2:printf("请输入修改后的班级:");
while(fflush(stdin),scanf("%s",banji)!=1) printf("请输入有效信息:");
if(Deliberation()) strcpy((*origin)->banji,banji);break;
case 3:CurriculumChange(&(*origin)->curriculum);break;
case 4:return;
default:;
}
}
}
void anew(Students* origin)
{
Students now=(Students)malloc(sizeof(students)),forever=*origin;
if(!now){printf("申请学生节点失败!\n");exit(1);}
char banji[10],name[10],number[15],gender;
Curriculums previous,curriculum;
int i=1;
while(i)
{
printf("请输入学号:");
while(fflush(stdin),scanf("%s",now->number)!=1) printf("请输入有效信息:");
while(forever)
{
if(!strcmp(now->number,forever->number))
{
printf("学号应具有唯一性!\n");
break;
}
else if(!(forever->next)) i=0;
forever=forever->next;
}
}
printf("请输入姓名:");
while(fflush(stdin),scanf("%s",now->name)!=1) printf("请输入有效信息:");
printf("请输入性别(f/m/F/M):");
while(((gender=getche())!='f')&&(gender!='M')&&(gender!='m')&&(gender!='F')){printf("\n请输入有效选项(f/F/m/M):");continue;}
printf("\n你输入的是%c\n",gender);
(gender=='f'||gender=='F')?strcpy(now->gender,"女"):strcpy(now->gender,"男");
printf("请输入班级:");
while(fflush(stdin),scanf("%s",now->banji)!=1) printf("请输入有效信息:");
now->next=(*origin)->next;
now->pre=(*origin);
(*origin)->next=now;
printf("请输入学生课程信息(高数 大一 66.6):");
if(!(curriculum=now->curriculum=(Curriculums)malloc(sizeof(curriculums))))
{printf("请求课程信息失败!\n");exit(1);}
curriculum->next=curriculum->pre=NULL;
fflush(stdin);
scanf("%s%s%f",curriculum->curriculum,curriculum->semester,&curriculum->score);
previous=curriculum;
if(!(curriculum=(Curriculums)malloc(sizeof(curriculums))))
{printf("请求课程信息失败!\n");exit(1);}
printf("请输入下一门课程信息(分数<=0结束):");
while(1)
{
while(fflush(stdin),(scanf("%s%s%f",curriculum->curriculum,curriculum->semester,&curriculum->score)==3))
{
if(curriculum->score<=0)
{
free(curriculum);
return;
}
curriculum->next=previous->next;
curriculum->pre=previous;
previous->next=curriculum;
if(!(curriculum=(Curriculums)malloc(sizeof(curriculums)))){
printf("请求课程信息失败!\n");exit(1);}
printf("请输入下一门课程信息(分数<=0结束):");
}
}printf("学生%s信息添加成功!\n",now->name);
}
void shower(Students origin)
{
Students current=origin;
Curriculums now;
printf("班级\t 名称\t学号\t性别课程-学期-成绩\n");
while(current)
{
now=current->curriculum;
printf("%s---%s---%s---%s-%s-%s-%.2f\t",current->banji,current->name,current->number,current->gender,now->curriculum,now->semester,now->score);
while(now=now->next)
printf("%s-%s-%.2f\t",now->curriculum,now->semester,now->score);
printf("\n");
current=current->next;
}
printf("数据输出成功!\n");
}
void showerone(Students origin)
{
Students current=origin;
Curriculums now;
printf("班级\t 名称\t学号\t性别课程-学期-成绩\n");
now=current->curriculum;
printf("%s---%s---%s---%s-%s-%s-%.2f\t",current->banji,current->name,current->number,current->gender,now->curriculum,now->semester,now->score);
while(now=now->next)
printf("%s-%s-%.2f\t",now->curriculum,now->semester,now->score);
printf("\n");
}
void searchclasscurriculumrank(Students origin){
char banji[10],curriculum[20];
int i=0,j,k,num;
Students now=origin,primitive=origin;
Curriculums current;
ones a;
Ones newone,previous=NULL,initial=NULL;
printf("请输入班级和课程(计算机217 高数):");
while(fflush(stdin),scanf("%s%s",banji,curriculum)!=2) printf("请输入有效信息:");
while(now)
{
if(!strcmp(now->banji,banji))
{
current=now->curriculum;
while(current)
{
if(!strcmp(current->curriculum,curriculum))
{
++i;break;
}
current=current->next;
}
}
now=now->next;
}
if(!i)
{
printf("无此课程或班级!\n");
return;
}
if(!(initial=newone=(Ones)malloc(sizeof(ones)*(num=i))))
{printf("申请信息失败!\n");exit(1);}
while(primitive)
{
if(!strcmp(primitive->banji,banji))
{
current=primitive->curriculum;
while(current)
{
if(!(strcmp(current->curriculum,curriculum)))
{
newone->score=current->score;
strcpy(newone->number,primitive->number);
strcpy((newone++)->name,primitive->name);
}
current=current->next;
}
}
primitive=primitive->next;
}
previous=newone=initial;
for(i=1;i<num;++i)
{
a=previous[i];
j=i-1;
while(j>=0&&previous[j].score<a.score)
{
previous[j+1]=previous[j];
--j;
}
previous[j+1]=a;
}
for(i=0;i<num;++i)
printf("%d--%s--%s:%.2f\n",i+1,previous[i].number,previous[i].name,previous[i].score);
printf("成绩输出成功!\n");
}
void freeall(Students* origin,Loggers* key)
{
if(*origin)
{
Students current=*origin,previous;
Curriculums now,pre;
while(current)
{
now=current->curriculum;
while(now)
{
pre=now;
now=now->next;
free(pre);
}
previous=current;
current=current->next;
free(previous);
}
}
Loggers p=*key,q;
while(q=p,p=p->next)
free(q);
free(q);
printf("数据释放成功!\n");
}
void deletesthroughnumber(Students* origin)
{
if(!*origin) exit(1);
if(!(*origin)->next&&!(*origin)->pre) exit(1);
else if(!(*origin)->next)
(*origin)->pre->next=NULL;
else if(!(*origin)->pre)
{
Curriculums previous,current=(*origin)->curriculum;
strcpy((*origin)->banji,"");
strcpy((*origin)->name,"");
strcpy((*origin)->number,"");
strcpy((*origin)->gender,"");
strcpy(current->semester,"");
strcpy(current->curriculum,"");
current->score=Fault;
while(current=current->next)
{
previous=current;
current=current->next;
free(previous);
}
(*origin)->curriculum->next=NULL;
printf("删除成功!\n");
return;
}
else
{
(*origin)->pre->next=(*origin)->next;
(*origin)->next->pre=(*origin)->pre;
}
free(*origin);
printf("删除成功!\n");
}
void impartstuinfo(Students q)
{
FILE *fp=fopen(Outfilestu,"w");
if(!fp){printf("写入文件%s打开失败!\n",Outfilestu);exit(1);}
Students current=q;Curriculums now;
while(current)
{
if(strcmp(current->name,""))
{
now=current->curriculum;
fprintf(fp,"#%s %s %s %s %s %s %.2f",current->banji,current->name,current->number,current->gender,now->curriculum,now->semester,now->score);
while(now=now->next)
fprintf(fp,"$ %s %s %.2f",now->curriculum,now->semester,now->score);
fputc('\n',fp);
}
current=current->next;
}
fclose(fp);
printf("学生信息写入文件%s成功!\n",Outfilestu);
}
Students stuinfoget()
{
FILE *fp=fopen(Infilestu,"r");
if(!fp){printf("文件%s打开失败,学生信息读取失败!\n",Infilestu);exit(1);}
Students current,previous=NULL,origin;
Curriculums now,pre=NULL;
char c=' ';
while(!feof(fp))
{
while(((c=='#')||((c=fgetc(fp))=='#'))&&c!=EOF)
{
if(!(current=(Students)malloc(sizeof(students)))){printf("内存不足,申请学生信息失败!\n");exit(1);}
if(fscanf(fp,"%s%s%s%s",current->banji,current->name,current->number,current->gender)==4)
{
current->next=current->pre=NULL;
if(!previous) origin=current;
if(!(now=current->curriculum=malloc(sizeof(curriculums)))){
printf("内存不足,申请学生%s课程信息失败!\n",current->name);exit(2);}
if(fscanf(fp,"%s%s%f",now->curriculum,now->semester,&now->score)==3)
now->next=now->pre=NULL;
pre=now;
while((c=fgetc(fp))=='$')
{
if(!(now=malloc(sizeof(curriculums)))){
printf("内存不足,申请学生%s课程信息失败!\n",current->name);exit(3);}
if(fscanf(fp,"%s%s%f",now->curriculum,now->semester,&now->score)==3)
{
now->next=pre->next;
now->pre=pre;
pre->next=now;
}
pre=now;
}
}
if(previous)
{
current->next=previous->next;
current->pre=previous;
previous->next=current;
}
previous=current;
}
}
fclose(fp);
printf("学生信息读取成功!\n");
return origin;
}
void DeleteTable(Students* origin)
{
Students now;
int todo;
char number[15],name[10];
while(1)
{
printf("请输入您想要进行的操作:1.按学号删除学生\t2.按名称查询学生\t3.按学号查询学生\t4.添加学生信息\t5.按学号修改学生信息\t6.退出(1/2/3/4/5/6):");
while(fflush(stdin),scanf("%d",&todo)!=1||todo<1||todo>6) printf("请输入有效选项(1-6):");
switch(todo)
{
case 1:if(!(now=searchnumber(*origin))) break;
deletesthroughnumber(&now);break;
case 2:printf("请输入待查找的名称(重庆):");
while(fflush(stdin),scanf("%s",name)!=1) ;
searchname(*origin,name,0);break;
case 3:searchnumber(*origin);break;
case 4:anew(origin);break;
case 5:if(!(now=searchnumber(*origin))) break;
changeable(&now);break;
case 6:return;
default:;
}
}
}
Students searchnumber(Students pre)
{
printf("请输入您想要查询的学生学号(12345678901):");
char number[15];
Students now=pre;
while(fflush(stdin),scanf("%s",number)!=1) printf("请输入正确学号(12345678901):");
while(now)
{
if(!strcmp(now->number,number))
{
showerone(now);
return now;
}
else if(!(now->next))
{
printf("无学号为%s的学生!\n",number);
return NULL;
}
now=now->next;
}
}
Students searchname(Students pre,char*name,int num)
{
int number=num;
Students now=pre;
while(now)
{
if(!strcmp(now->name,name))
{
showerone(now);
searchname(now->next,name,++number);
return now;
}
else if(!(now->next)&&!number)
{
printf("无名称为%s的学生!\n",name);
return NULL;
}
now=now->next;
}
}
void norsearch(Students q)
{
int todo;
char name[10];
while(1)
{
printf("请输入您想要进行的操作:1.按名称查找学生\t2.按学号查找学生\t3.查询某班级某门课程排名\t4.退出:");
while(fflush(stdin),scanf("%d",&todo)!=1||todo<1||todo>4) printf("请输入合理选项(1/2/3/4):");
switch(todo)
{
case 1:printf("请输入待查找的名称:");
while(fflush(stdin),scanf("%s",name)!=1) printf("请输入正确数据:");
searchname(q,name,0);
break;
case 2:searchnumber(q);break;
case 3:searchclasscurriculumrank(q);break;
case 4:return;
default:;
}
}
}
void initaccountes(Loggers* q){
FILE *fp=fopen(Infileaccount,"r");
if(!fp){printf("用户登陆信息文件打开失败!\n");exit(2);}
(*q)->next=NULL;
Loggers current=(Loggers)malloc(sizeof(loggers));
if(!current){printf("初始化账户内存不够!\n");exit(3);}
printf("登录账号\t密码 身份\n");
while(fscanf(fp,"%s%s%d",current->account,current->password,¤t->users)==3)
{
printf("%s\t%s\t%d\n",current->account,current->password,current->users);
current->next=(*q)->next;
(*q)->next=current;
if(!(current=(Loggers)malloc(sizeof(loggers)))){
printf("初始化账户内存不够!\n");exit(3);}
}
printf("用户登陆信息显示成功!\n用户登陆信息文件%s内容读取成功!\n",Infileaccount);
fclose(fp);//关闭文件
}
void tablelog(Loggers q,Students qq){
initaccountes(&q);
shower(qq);
printf(" _____________________________________\n");
printf("| 欢迎来到学生管理系统 |\n");
printf("|_____________________________________|\n");
char account1[15],password1[15];
Loggers p,r;
int opportunity=Attemptingpassword,user,key=1;
while(key)
{
printf("请依次正确输入您的账号,密码和用户类型(123456 abcdef 1普通用户/0管理员):");
while(fflush(stdin),scanf("%s%s%d",account1,password1,&user)!=3||user<0||user>1) printf("请输入正确数据格式以及状态(0/1):");
p=r=q;
while(p=p->next)
if(!strcmp(account1,p->account)&&!(strcmp(password1,p->password)))
if(user)
{
printf("普通用户账号登陆成功!\n");
key=0;
norsearch(qq);
freeall(&qq,&q);
break;
}
else
{
printf("管理员账号登陆成功!\n");
key=0;
DeleteTable(&qq);//进入管理员操作页面
impartstuinfo(qq);//保存管理员操作后的信息
freeall(&qq,&q);
break;
}
if(!p)
{
r=q;
if(--opportunity)
{
while(r=r->next)
{
if(!strcmp(account1,r->account))
{
printf("密码错误!您还有%d次有效机会!\n",opportunity);break;
}
else if(!strcmp(password1,r->password))
{
printf("账号错误!您还有%d次有效机会!\n",opportunity);break;
}
}
if(!r)
printf("账号密码错误!您还有%d次有效机会!\n", opportunity);
}
else
{
printf("很抱歉,机会已耗尽,您的账户已被锁定,请稍后尝试\n",opportunity);
freeall(&qq,&q);
exit(1);
}
}
}
}
版权声明:本文标题:《C语言》学生信息管理系统:链表(嵌套)+文件 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1725943776h896656.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论