(作者:KX)
(code:c)
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
struct STU
{
char name[10];
int id;
int age;
char address[50];
struct STU *next;
};
int login();
struct STU *menu(struct STU *);
struct STU *creatList();
struct STU *getStuList(char *);
int putStuList(struct STU *);
struct STU *getRencent();
int putRecent(char *);
int searchStu(struct STU *,char);
int sortList(struct STU *);
int insertStu(struct STU *);
void deleteStu(struct STU *);
int countStu(struct STU *);
void tapToContinue(char *);
char getcheln();
int tipOpen(struct STU *);
void exitSystem(int);
char *strSub(int,int,char *);
void inputPass(char *);
int modifyPass();
int main()
{
if(login()!=1)
{
exit(0);
}
struct STU *head=NULL;
head=getRencent();
do
{
head=menu(head);
}while(1);
return 0;
}
int login()
{
char getPass[20],truePass[20];
FILE *fp;
if((fp=fopen("admin.dat","r"))!=NULL)
{
fgets(truePass,20,fp);
fclose(fp);
do
{
system("cls");
printf("┏━━━━━━┓\n");
printf("┃学生管理系统┃\n");
printf("┗━━━━━━┛\n");
printf("请输入密码:\n");
inputPass(getPass);
if(strcmp(truePass,getPass)==0)
{
tapToContinue("登陆成功!\n");
return 1;
}
else
{
tapToContinue("密码错误!\n");
}
}while(getPass[0]!='0' && getPass[1]!=0);
}
else
{
fp=fopen("admin.dat","w");
fputs("123456",fp);
fclose(fp);
tapToContinue("您的初始密码为123456,请尽快修改密码\n");
return 1;
}
return 0;
}
/************************
函数:主菜单
输入:列表链表头结点地址
返回:处理后的链表头结点地址
************************/
struct STU *menu(struct STU *head)
{
char command;
system("cls");
printf("┏━━━━━━┓\n");
printf("┃学生管理系统┃\n");
printf("┣━━━━━━┫\n");
if(head==NULL)
{
printf("┃暂未打开列表┃\n");
}
else
{
int stuAmount=countStu(head);
printf("┃一共%2d个学生┃\n",stuAmount);
}
printf("┣━━━━━━┫\n");
printf("┃ 请输入命令 ┃\n");
printf("┣━━━━━━┫\n");
if(head!=NULL)
{
printf("┃ 1.查询学生 ┃\n");
printf("┃ 2.添加学生 ┃\n");
printf("┃ 3.删除学生 ┃\n");
printf("┃ 4.排序列表 ┃\n");
printf("┃ 5.打印列表 ┃\n");
printf("┃ 6.保存列表 ┃\n");
}
printf("┃ 8.新建列表 ┃\n");
printf("┃ 9.读取列表 ┃\n");
printf("┃ a.修改密码 ┃\n");
printf("┃ 0.退出系统 ┃\n");
printf("┗━━━━━━┛\n");
command=getch();
switch(command)
{
case'1'://搜索学生
if(tipOpen(head))
{
searchStu(head,'0');
tapToContinue("");
}
break;
case'2'://插入学生
if(tipOpen(head))
{
insertStu(head);
tapToContinue("");
}
break;
case'3'://删除学生
if(tipOpen(head))
{
searchStu(head,'A');
deleteStu(head);
tapToContinue("");
}
break;
case'4'://排序列表
if(tipOpen(head))
{
if(sortList(head))
{
searchStu(head,'A');
tapToContinue("");
}
}
break;
case'5'://打印列表
if(tipOpen(head))
{
searchStu(head,'A');
tapToContinue("");
}
break;
case'6'://保存列表
if(tipOpen(head))
{
putStuList(head);
tapToContinue("");
}
break;
case'8'://创建列表
head=creatList(head);
tapToContinue("");
break;
case'9'://读取列表
head=getStuList("");
tapToContinue("");
break;
case'0'://退出系统
exitSystem(0);
break;
case'a'://修改密码
modifyPass();
break;
}
return head;
}
/*******************************
函数:创建列表并插入学生
返回创建的列表首地址或原来的首地址
********************************/
struct STU* creatList(struct STU *head)
{
struct STU *pcur,*newHead;
newHead=pcur=(struct STU*)malloc(sizeof(struct STU));
newHead->next=NULL;
if(head!=NULL)
{
printf("创建新列表将舍弃当前列表\n");
}
if(!insertStu(newHead))
{
return head;
}
printf("链表创建完成\n");
return newHead;
}
/*******************************
函数:打开最后打开的列表
返回列表链表首地址 NULL未成功打开
********************************/
struct STU *getRencent()
{
char command;
FILE *recent;
char recentFile[20],recentFileTemp[20];
if((recent=fopen("recentList.dat","r"))==NULL)
{
return NULL;
}
fgets(recentFile,20,recent);
fclose(recent);
strcpy(recentFileTemp,recentFile);
if(recentFileTemp[11])
{
recentFileTemp[8]=recentFileTemp[9]=recentFileTemp[10]='.';
recentFileTemp[11]=0;
}
printf("┏━━━━━━━━━━┓\n");
printf("┃是否打开上次的列表?┃\n");
printf("┣━━━━━━━━━━┫\n");
printf("┃上次打开:%11s┃\n",recentFileTemp);
printf("┣━━━━━┳━━━━┫\n");
printf("┃ 1.是 ┃ 2.否 ┃\n");
printf("┗━━━━━┻━━━━┛\n");
command=getch();
if(command!='1')
{
return NULL;
}
struct STU *head=getStuList(recentFile);
tapToContinue("");
return head;
}
/*******************************
函数:记录打开的列表名称
返回值:1成功记录 0未记录
********************************/
int putRecent(char *fileName)
{
if(!fileName)
{
return 0;
}
FILE *recent;
recent=fopen("recentList.dat","w");
fputs(fileName,recent);
fclose(recent);
return 1;
}
/*******************************
函数:打开名为fileName的列表
实参fileName为空则由用户输入fileName
返回fileName链表的首地址
********************************/
struct STU *getStuList(char *fileName)
{
struct STU *pcur,*head,*pnew;
head=(struct STU *)malloc(sizeof(struct STU));
FILE *fp;
head->next=NULL;
pcur=head;
if(!fileName[0])
{
fileName=(char*)calloc(20,sizeof(char));
printf("请输入导入文件名:\n");
scanf("%s",fileName);
}
printf("打开:%s...\n",fileName);
if((fp=fopen(fileName,"r"))==NULL)
{
printf("打开失败!\n");
free(fileName);
return NULL;
}
putRecent(fileName);
fseek(fp,1,1);
while(!feof(fp))
{
fseek(fp,-1,1);
pnew=(struct STU *)malloc(sizeof(struct STU));
pnew->next=NULL;
fread(pnew,sizeof(struct STU),1,fp);
pcur->next=pnew;
pcur=pcur->next;
fgetc(fp);
}
fclose(fp);
printf("读取完成!\n");
return head;
}
/*******************************
函数:写入列表
返回值: 1写入成功 2失败
********************************/
int putStuList(struct STU *head)
{
struct STU *pcur=head->next;
char fileName[20];
FILE *fp;
while(1)
{
printf("请输入要保存的文件名:\n");
scanf("%s",fileName);
if(strcmp(".dat",strSub(strlen(fileName)-4,100,fileName))==0)
{
tapToContinue("不能以dat为扩展名\n");
}
else
{
break;
}
}
remove(fileName);
if((fp=fopen(fileName,"a"))==NULL)
{
printf("打开失败!\n");
return 0;
}
while(pcur!=NULL)
{
fwrite(pcur,sizeof(struct STU),1,fp);
pcur=pcur->next;
}
fclose(fp);
putRecent(fileName);
printf("保存完成!:%s\n",fileName);
return 1;
}
/*******************************
函数:计算列表中学生的总个数
返回列表中学生总个数
********************************/
int countStu(struct STU *head)
{
struct STU *pcur;
int count=0;
pcur=head;
while(pcur->next!=NULL)
{
pcur=pcur->next;
count++;
}
return count;
}
/*******************************
函数:查找学生
返回查找到的学生个数
********************************/
int searchStu(struct STU *head,char command)
{
struct STU *pcur;
int searchInt,count=0;
char searchStr[50];
if(command!='A')
{
while(!(command=='1' || command=='2' || command=='3' || command=='4'))
{
printf("┏━━━━━━┓\n");
printf("┃输入查找依据┃\n");
printf("┣━━━━━━┫\n");
printf("┃1.按姓名查找┃\n");
printf("┃2.按学号查找┃\n");
printf("┃3.按年龄查找┃\n");
printf("┃4.按地址查找┃\n");
printf("┃0.返回上一层┃\n");
printf("┗━━━━━━┛\n");
command=getcheln();
if(command=='0')
{
return 0;
}
}
printf("\n输入查找关键字:\n");
if(command=='1' || command=='4')
{
scanf("%s",searchStr);
}
else if(command=='2' || command=='3')
{
scanf("%d",&searchInt);
}
}
pcur=head;
printf("┏━━━━━┳━━━━━┳━━┳━━━━━━━━━━━━━━━━━━━━┓\n");
printf("┃%10s┃%10s┃%4s┃%40s┃\n","姓名","学号","年龄","地址");
while(pcur->next!=NULL)
{
pcur=pcur->next;
if (command=='A'
|| (command=='1' && strstr(pcur->name,searchStr)!=NULL)
|| (command=='4' && strstr(pcur->address,searchStr)!=NULL)
|| (command=='2' && pcur->id==searchInt)
|| (command=='3' && pcur->age==searchInt))
{
printf("┣━━━━━╋━━━━━╋━━╋━━━━━━━━━━━━━━━━━━━━┫\n");
printf("┃%10s┃%10d┃%4d┃%40s┃\n",pcur->name,pcur->id,pcur->age,pcur->address);
count++;
}
}
printf("┗━━━━━┻━━━━━┻━━┻━━━━━━━━━━━━━━━━━━━━┛\n");
return count;
}
/*******************************
函数:列表排序
返回排序依据 0:未排序
********************************/
int sortList(struct STU *head)
{
char command;
struct STU *pcur,*ptemp,*pmax,*pswap,*pcurNext,*pmaxNext;
pswap=(struct STU *)malloc(sizeof(struct STU));
while(!(command=='1' || command=='2' || command=='3' || command=='4'))
{
printf("┏━━━━━━┓\n");
printf("┃输入排序依据┃\n");
printf("┣━━━━━━┫\n");
printf("┃1.按姓名排序┃\n");
printf("┃2.按学号排序┃\n");
printf("┃3.按年龄排序┃\n");
printf("┃4.按地址排序┃\n");
printf("┃0.返回上一层┃\n");
printf("┗━━━━━━┛\n");
command=getcheln();
if(command=='0')
{
return 0;
}
}
pcur=head->next;
while(pcur!=NULL)
{
pmax=pcur;
for(ptemp=pcur;ptemp!=NULL;ptemp=ptemp->next)
{
if((command=='1' && strcmp(ptemp->name,pmax->name)<0)
|| (command=='4' && strcmp(ptemp->address,pmax->address)<0)
|| (command=='2' && ptemp->id<pmax->id)
|| (command=='3' && ptemp->age<pmax->age))
{
pmax=ptemp;
}
}
pcurNext=pcur->next;
pmaxNext=pmax->next;
memcpy(pswap,pcur,sizeof(struct STU));
memcpy(pcur,pmax,sizeof(struct STU));
memcpy(pmax,pswap,sizeof(struct STU));
pcur->next=pcurNext;
pmax->next=pmaxNext;
pcur=pcur->next;
}
printf("排序完成!\n");
return command-'0';
}
/*******************************
函数:插入学生
返回插入学生的数量
********************************/
int insertStu(struct STU *pcur)
{
struct STU *pnew;
int i;
char name[10];
for(i=0;;i++)
{
printf("请输入第%d个学生的信息(姓名、学号、年龄、地址),用空格隔开:\n",i+1);
scanf("%s",name);
if(name[0]=='0' && name[1]==0)
{
break;
}
pnew=(struct STU*)malloc(sizeof(struct STU));
pnew->next=pcur->next;
pcur->next=pnew;
pcur=pnew;
strcpy(pcur->name,name);
scanf("%d%d%s",&pcur->id,&pcur->age,pcur->address);
}
return i;
}
/*******************************
函数:删除学生
********************************/
void deleteStu(struct STU *head)
{
char c;
struct STU *pcur,*ptemp;
printf("请输入要删除学生的学号(多个用空格隔开):\n");
int delId;
while(scanf("%c",&c),c!='\n')
{
if(c==' ' || c==',')
{
continue;
}
delId=c-'0';
pcur=head;
while(pcur->next!=NULL)
{
ptemp=pcur;
pcur=pcur->next;
if(pcur->id==delId)
{
ptemp->next=pcur->next;
free(pcur);
printf("删除成功 学号:%d!\n",delId);
pcur=ptemp;
}
}
}
}
/*******************************
函数:点击任意键继续效果
********************************/
void tapToContinue(char *tip)
{
if(tip[0]==0)
{
printf("\n点击任意键继续...\n");
}
else
{
printf("%s",tip);
}
getch();
}
/*******************************
函数:getche()并换行
返回读取到的字符
********************************/
char getcheln()
{
char c=getch();
printf("%c\n",c);
return c;
}
/*******************************
函数:未打开列表提示打开或创建一个列表
返回值:1已打开 0未打开
********************************/
int tipOpen(struct STU *head)
{
if(head==NULL)
{
printf("还没有打开或创建列表!\n");
tapToContinue("");
return 0;
}
return 1;
}
/*******************************
函数:退出系统确认
********************************/
void exitSystem(int n)
{
char c;
printf("┏━━━━━━━┓\n");
printf("┃确定退出系统?┃\n");
printf("┣━━━┳━━━┫\n");
printf("┃1.是 ┃ 2.否┃\n");
printf("┗━━━┻━━━┛\n");
c=getch();
if(c=='1')
{
printf("已退出\n");
exit(n);
}
}
/*******************************
函数:字符串截取
从第start个字符截取到第end个字符
返回截取后的字符串
********************************/
char *strSub(int start,int end,char *str)
{
int lenth=strlen(str);
if(start>end || start>=lenth)
{
return 0;
}
char *str2=(char *)calloc(lenth+1,sizeof(char));
strcpy(str2,str);
if(end<lenth)
{
str2[end]=0;
}
return str2+start;
}
/*****************************
函数:输入密码显示 *
输入:要输入的字符串的地址
*****************************/
void inputPass(char *str)
{
char c;
int i;
for(i=0;i<19;)
{
//printf("%s\n",str);
c=getch();
if(c=='\r')
{
break;
}
else if(c==8){
str[i-1]=0;
i=i==0?0:(i-1);
printf("%c%c%c",8,' ',8);
}
else if((c>='0' && c<='9') || (c>='a' && c<='z'))
{
str[i]=c;
str[++i]=0;
putchar('*');
}
}
putchar('\n');
}
/***********************
函数:修改密码
返回值:1 修改成功 0未修改或修改失败
***********************/
int modifyPass()
{
char getPass[20],truePass[20],putPass[2][20];
FILE *fpr,*fpw;
int result=0;
fpr=fopen("admin.dat","r");
fgets(truePass,20,fpr);
do
{
system("cls");
printf("┏━━━━┓\n");
printf("┃修改密码┃\n");
printf("┗━━━━┛\n");
printf("请输入原密码(输入0取消):\n");
inputPass(getPass);
if(getPass[0]=='0' && getPass[1]==0)
{
break;
}
if(strcmp(truePass,getPass)!=0)
{
tapToContinue("原密码错误!\n");
continue;
}
while(!(putPass[0][0]=='0' && putPass[0][1]==0))
{
system("cls");
printf("请输入新密码(仅支持数字、小写字母,输入0取消):\n");
inputPass(putPass[0]);
if(putPass[0][0]=='0' && putPass[0][1]==0)
{
return 0;
}
if(strlen(putPass[0])<6)
{
tapToContinue("新密码长度太短了,至少要六位!\n");
continue;
}
printf("再次输入密码:\n");
inputPass(putPass[1]);
if(strcmp(putPass[0],putPass[1])!=0)
{
tapToContinue("两次输入的密码不一致!\n");
continue;
}
fpw=fopen("admin.dat","w");
fputs(putPass[0],fpw);
tapToContinue("密码修改成功!\n");
fclose(fpw);
result=1;
break;
}
}while((getPass[0]!='0' && getPass[1]!=0) && result!=1);
fclose(fpr);
return result;
}
(/code)