学生管理系统---C语言版

//我把这个系统设计为可以自己来选择是否退出,而不是一般情况下的执行完一个动作后就马上退出
#include
#include
#include
#include
#include
#define LENGTH 5 //定义学科的科目数
#define MES (struct StudentMessage *)malloc(sizeof(struct StudentMessage))
#define MAR (struct StudentMark *)malloc(sizeof(struct StudentMark))
typedef struct StudentMessage//宏定义基本信息的结构体
{
char name[20];//名字
int id; //学号
char sex[10]; //性别
char college[20];//学院
int Class;//用大写字母来区别于class关键字 班级
struct StudentMessage *next;//建立一个指向后面的链表
}MESSAGE;
typedef struct StudentMark//宏定义成绩信息的结构体
{
char name[20];
int id;
struct subject//学科信息的结构体
{
char subname[20];
float score;
}sub[LENGTH];//以数组的形式,表示有 LENGTH 科
double total;
struct StudentMark *next;//指向后面的链表
}MARK;
void MainMenu(MESSAGE *head,MARK *top);//主菜单函数
void SearchStuMenu(MESSAGE *head); //查找信息的菜单
MESSAGE *AddStudent(MESSAGE *head); //增加个人信息的函数
MESSAGE *DeleteMenu(MESSAGE *head,MARK *top); //删除菜单
MESSAGE *ChangeStu(MESSAGE *head,MARK *top); //修改个人信息的菜单选项
void SearchStuOne(MESSAGE *head); //查找个人基本信息
void SearchStuClass(MESSAGE *head); //查找班级基本信息
void ScanStuAll(MESSAGE *head); //浏览所有学生的基本信息
MESSAGE *DeleteStuOne(MESSAGE *head); //删除个人基本信息
MESSAGE *DeleteStuClass(MESSAGE *head); //删除班级基本信息
MESSAGE *DeleteStuAll(MESSAGE *head); //删除所有人的基本信息
MESSAGE *Change(MESSAGE *p); //修改个人信息具体操作
void SearchStuMarkMenu(MARK *top); //查找学生成绩信息的主菜单
MARK *AddStuMark(MARK *top); //添加学生成绩信息
MARK *DeleteStuMark(MARK *top); //删除学生成绩信息
MARK *ChangeStuMark(MARK *top); //修改学生成绩信息菜单
MARK *ChangeMark(MARK *find); //修改学生成绩信息具体操作
MESSAGE *ReadFileStu(MESSAGE *head); //从文件中读取个人基本信息
MARK *ReadFileStuMark(MARK *top); //从文件中读取个人成绩信息
void SaveFileStu(MESSAGE *head); //保存个人基本信息至文件
void SaveFileStuMark(MARK *top); //保存成绩信息至文件
void MainMenu(MESSAGE *head,MARK *top); //把主菜单用函数来表示,利于后面的调用
void ManageFile(MESSAGE *head,MARK *top);
void ManageStu(MESSAGE *head,MARK *top);
void ManageStuMark(MESSAGE *head,MARK *top);


int main()
{

int choose=0;int choose5=0; char answer1=0;
MESSAGE *head=NULL;
MARK *top=NULL;
MainMenu(head,top);
}


void MainMenu(MESSAGE *head,MARK *top)
{
int choose=0;
int choose5=0;
char answer1=0;
char answer2=0;
char answer3=0;
printf("*********

***********************************************************************\n");
printf(" 学生信息管理系统 \n\n");
printf(" 1.学生基本信息管理\n");
printf(" 2.学生成绩信息管理\n");
printf(" 3.文件保存及查询操作\n");
printf(" 4.退出"); //小记:如果不自己构造函数,倒是可以很自由的用goto穿来穿去,不过不太现实也不太合理,嘿嘿 ,goto能不用则不用
printf("\n请选择:");
scanf("%d",&choose);
switch(choose)
{
case 1:
ManageStu(head,top);
break;
case 2:
ManageStuMark(head,top);
break;
case 3:
ManageFile(head,top);
break;
case 4:
exit(1);//退出
break;
}
}


void ManageStuMark(MESSAGE *head,MARK *top)
{
int choose=0;
char answer1=0;
do
{
printf("\n\n*****************************************************************************\n");
printf(" 学生成绩信息管理\n");
printf(" 1.查找成绩信息\n");
printf(" 2.添加成绩信息\n");
printf(" 3.删除成绩信息\n");
printf(" 4.修改成绩信息\n");
printf(" 5.返回");
printf("\n请选择:");fflush(stdin);
scanf("%d",&choose);
switch(choose)
{
case 1:
SearchStuMarkMenu(top);
break;
case 2:
top=AddStuMark(top);
break;
case 3:
top=DeleteStuMark(top);
break;
case 4:
top=ChangeStuMark(top);
case 5:
MainMenu(head,top);//仔细思考这里为什么要返回head 和top 两个链表的开端??
break;
}
printf("你还想继续操作吗??(y or n)");
fflush(stdin);
scanf("%c",&answer1);
}while(tolower(answer1)=='y');
}


void ManageStu(MESSAGE *head,MARK *top)
{
int choose=0;
char answer1=0;
do
{
printf("\n\n**********************************************************************************\n\n");
printf(" 学生基本信息管理\n");
printf(" 1.查找信息\n");
printf(" 2.添加信息\n");
printf(" 3.删除信息\n");
printf(" 4.修改信息\n");
printf(" 5.返回\n");
printf("请选择:");
scanf("%d",&choose);
if(choose==1)
SearchStuMenu(head);//这个函数不需要返回值
else if(choose==2)
head=AddStudent(head);//这个函数需要返回值,因为需要返回head指针,方便后面的操作
else if(choose==3)
head=DeleteMenu(head,top);//同上
else if(choose==4)
head=ChangeStu(head,top);//同上
else if

(choose==5)
MainMenu(head,top);
else
printf("您输错了");
printf("\nDo you want to deal with again??(y or n)");
fflush(stdin);
scanf("%c",&answer1);
}while(tolower(answer1)=='y');
}


void ManageFile(MESSAGE *head,MARK *top)
{
char answer1=0;
int choose=0,choose5=0;
printf("\n\n******************************************************************\n");
printf(" 文件管理\n");
printf(" 1.从文件中读取信息\n");
printf(" 2.保存学生信心至文件\n");
printf(" 3.返回\n");
printf("请选择:");
fflush(stdin);
scanf("%d",&choose);
fflush(stdin);
if(choose==1)
{
do
{
printf(" 1.读取学生基本信息\n ");
printf(" 2.读取学生成绩信息\n");
printf(" 3.返回\n");
printf("请选择:");
scanf("%d",&choose5);//bug:为什么???这里只要输入2就会弹出内存错误啊 答:因为我忘记加上&了。。。悲剧
switch(choose5)
{
case 1:
head=ReadFileStu(head);
break;
case 2:
top=ReadFileStuMark(top);
break;
case 3:
ManageFile(head,top);//应该只返回到上一层菜单,而不是直接返回到最早一层的菜单,通过再次构造函数解决了这个问题
break;
}
printf("\n你还想进行本项操作吗???(y or n)");
fflush(stdin);
scanf("%c",&answer1);
}while(tolower(answer1)=='y');
}
else if(choose==2)
{
do
{
printf("\n 1.保存学生基本信息");
printf("\n 2.保存学生成绩信息");
printf("\n 3.返回");
printf("\n请选择:");
fflush(stdin);
scanf("%d",&choose);
switch(choose)
{
case 1:
SaveFileStu(head);
break;
case 2:
SaveFileStuMark(top);
break;
case 3:
ManageFile(head,top);//用调用函数来代替goto,应该只返回到上一层菜单,而不是直接返回到最早一层的菜单,通过再次构造函数解决了这个问题
break;
}
printf("\n你想继续进行本操作吗??(y or n)");
fflush(stdin);
scanf("%c",&answer1);
}while(tolower(answer1)=='y');
}
else if(choose==3)
MainMenu(head,top);
}


void SearchStuMenu(MESSAGE *head)
{
int choose=0;
fflush(stdin);
printf("\n\n1.查找个人信息");
printf("\n2.查找班级信息");
printf("\n3.查找全部信息");//类似的,还可以添上:查找整个学院,删除整个学院的信息
printf("\n请选择:");
scanf("%d",&choose);
switch(choose)
{
case 1:
SearchStuOne(head);
break;
case 2:
SearchStuClass(head);
break;
case 3:
ScanStuAll(head);
break;
default:
printf("\n您输错了!!");
}
}


MESSAGE *AddStudent(MESSAGE *head)
{
MESSAGE *p1=MES,*p2;
if(p1==NULL)
{
printf("There is no enough memory for p1!!");
exit(1);
}
//if(!p2)//觉得没有必要为p2分配内存了
//{
// prin

tf("There is no enough memory for p2!!!");
// exit(1);
//}
fflush(stdin);
printf("Please input the student's:\n ID:\n");
scanf(" %d",&p1->id);fflush(stdin);
printf("name:");
gets(p1->name);fflush(stdin);
printf("sex:");
gets(p1->sex);fflush(stdin);
printf("college:");//这个函数的关键所在,如何把新输入的这个学生添加到原先的链表中
gets(p1->college);fflush(stdin);
printf("class:");
scanf("%d",&p1->Class);fflush(stdin);
p1->next=NULL;
/*自己的另一种添加方法:把新的p1添加至末尾!!有一点小问题:这样只能输出第一次添加的信息,不能输入后面添加的信息,但不知道为什么
p2=head; //是不是因为末尾的指针没有指向NULL??????
while(head!=NULL)
head=head->next;
p1=head;
head=p2;*/
//下面是正确的方法:把新添加的p1添加到首位:
if(head!=NULL)
{
p2=head;
p1->next=p2; //直接p1-next=head;head=p1;这样也可以的
head=p1;
}
else
head=p1;
return head;
}


MESSAGE *DeleteMenu(MESSAGE *head,MARK *top)
{
int choose=0;
do
{
printf("\n1.删除个人信息");
printf("\n2.删除班级信息");
printf("\n3.删除全部信息");
printf("\n4.返回上一菜单");
printf("\nPlease input choose:");
scanf("%d",&choose);
switch(choose)
{
case 1:
head=DeleteStuOne(head);
break;
case 2:
head=DeleteStuClass(head);
break;
case 3:
head=DeleteStuAll(head);
break;
case 4:
ManageStu(head,top); //如果不用goto语句应该构造函数来返回到上一菜单
break;
default:
printf("您输错了");
break;
}
}while(choose!=1 && choose!=2 && choose!=3 && choose !=4);
return head;
}


MESSAGE *ChangeStu(MESSAGE *head,MARK *top)
{
char name[20];
int id=0;
int gole=0;//标志变量,用于反映是否查找到
int choose=0;
MESSAGE *p=MES;
if(!p)
{
printf("\nThere is no enough memory!!!!");
exit(1);
}
if(head!=NULL)
{
do
{
fflush(stdin);
p=head;//这里的初始化很重要。。。。
printf("\n1.姓名 2.学号 3.返回 ");
printf("\nPlease choose:");
scanf("%d",&choose);
fflush(stdin);
switch(choose)
{
case 1:
printf("Please input the name that you want to search:");
gets(name);fflush(stdin);
while(p!=NULL)
{
if(strcmp(name,p->name)==0)
{
p=Change(p);//声明函数,因为要用到好几次这个函数的内容,所以最好声明出来,方便些
gole++;
}
p=p->next;
}
if(gole==0)
printf("\nThere is no this person!!!!");
break;
case 2:
printf("Please input the ID:");
scanf("%d",&id);fflush(stdin);
while(p!=NULL)
{
if(id==p->id)
{
p=Change(p);
gole++;
}
p=p->next;
}
if(!gole)
printf("\nThere is no this person!!!!");
break;
case 3:
M

anageStu(head,top);
break;
}
}while(choose!=1 && choose!=2 && choose!=3);
}
else
{
printf("\n没有数据,无法修改");
}
return head;
}


void SearchStuOne(MESSAGE *head)
{
MESSAGE *p=head;
int id=0;
int gole=0;
int choose=0;
char name[20];
printf("\n1.学号查找 2.姓名查找 ");
scanf("%d",&choose);
fflush(stdin);
switch(choose)
{
case 1:
printf("请输入学号:");
scanf("%d",&id);
while(p!=NULL)
{
if(id==p->id)
{
printf("学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s ",p->id,p->name,p->sex,p->Class,p->college);
gole++;
}
p=p->next;
if(gole==0)
printf("没有您要找的人!!!");
}
break;
case 2:
printf("请输入姓名:");
gets(name);
while(p!=NULL)
{
if(strcmp(name,p->name)==0)
{
printf("学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s ",p->id,p->name,p->sex,p->Class,p->college);
gole++;
}
p=p->next;
if(!gole)
printf("你输入错了");
}
break;
}
}


void SearchStuClass(MESSAGE *head)
{
MESSAGE *p=head;
int Class=0;
int gole=0;
printf("请输入班级:");
scanf("%d",&Class);
while(p!=NULL)
{
if(Class==p->Class)
{
printf("学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s\n ",p->id,p->name,p->sex,p->Class,p->college);
gole++;
}
p=p->next;
}
if(!gole)
printf("您输错了");
else
printf("\nThere is %d information!!!",gole);
}


void ScanStuAll(MESSAGE *head)
{
MESSAGE *p=head;
int gole=0;
while(p!=NULL)
{
printf("\n学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s ",p->id,p->name,p->sex,p->Class,p->college);
gole++;
p=p->next;
}
printf("\nYou have scaned %d information",gole);
}


MESSAGE *DeleteStuOne(MESSAGE *head)
{
int id=0;int gole=0;
char name[20];
int choose=0;
char answer=0;
MESSAGE *p1=MES,*p2=MES,*find=MES,*p3=NULL;
if(!p1)
{
printf("There is no enough room for p1!!!");
exit(1);
}
if(!p2)
{
printf("There is no enough room for p2!!!");
exit(1);
}
if(!find)
{
printf("There is no enough room for find!!!");
exit(1);
}
if(head!=NULL)
{
p1=head;//这里有什么作用啊???
p2=head;//这里有什么作用啊!!!!
do
{
fflush(stdin);
printf("\n1.通过姓名删除 2.通过学号删除 3.返回");
printf("\n请选择:");
scanf("%d",&choose);
switch(choose)
{
case 1:
find=head;
fflush(stdin);
printf("\nPlease input the name");
gets(name);
while(find!=NULL)
{
if(strcmp(name,find->name)==0)
{
printf("\n学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s ",find->id,find->name,find->sex,find->Class,find->college);
gole++;
}
printf("\n");
find=find->next;
}
if(gole==0)
printf("输入错误");
else
{
fflush(stdin);
prin

tf("\n你确定要删除这个消息吗???");
scanf("%c",&answer);
if(tolower(answer)=='y')
{
while((p1->next!=NULL) && (strcmp(name,p1->name)!=0))//重点哈:似乎明白这个while语句的作用了,只有当找得到删除的人时才会进行删除工作,但这个代码确实太多余了
{
p2=p1;//问:这个语句有什么作用,不懂哎:让p2成为p1的前一个结点
p1=p1->next;
}
if(strcmp(name,p1->name)==0)
{
if(p1==head)
head=head->next;
else
p2->next=p1->next;//删除结点p1
free(p1);
}
printf("\n成功删除以上信息!!!");
}

}printf("请按任意键返回主菜单!!");
getch();
break;
case 2:
find=head;
fflush(stdin);
printf("\nPlease input the id:");
scanf("%d",&id);
while(find!=NULL)
{
if(id==find->id)
{
printf("\n学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s ",find->id,find->name,find->sex,find->Class,find->college);
gole++;
}
find=find->next;
}
if(!gole)
printf("您输入错误");
else
{
fflush(stdin);
printf("\n你确定要删除这条信息??????");
scanf("%c",&answer);
if(tolower(answer)=='y')
{
while((p1->next!=NULL) && (id!=p1->id))
{
p2=p1;
p1=p1->next;//使p2成为p1的前一个结点
}
if(p1==head)
{
p3=head;//觉得这里是很重要的一步
head=head->next;
free(p3);//觉得这一步也很重要!!!释放内存在任何时候都是很重要的
}
else
{
p2->next=p1->next;//删除结点p1
free(p1);
}
printf("成功删除以上信息!!!");
}
}
printf("请按任意键返回!");
getch();
break;
case 3:
//想一下如何设计返回主菜单的代码!!调用函数!!!!
break;
default :
printf("请按任意键返回!\n");
getch();
break;
}
}while(choose!=1 && choose!=2 && choose!=3 );
}
else
{
printf("没有信息,请先输入信息啊!!!");
printf("请按任意键返回\n");//怎么设计返回主菜单的代码??调用函数!!
getch();
}
return head;
}


MESSAGE *DeleteStuClass(MESSAGE *head)
{
MESSAGE *p1=NULL,*p2=NULL,*find=NULL;
int Class=0;int gole=0;
printf("\n请输入你想删除的班级");
scanf("%d",&Class);
find=head;
if(find==NULL)
printf("这里没有信息,无法删除");
while(find!=NULL)
{
p1=head;
p2=head;//这两个语句有什么作用???便于连接p1和p2
while((p1->next!=NULL) && (Class!=p1->Class))
{
p2=p1;//这个while循环之所以不会选出相同的,是因为每次选出来的都已经被删除出了链表了
p1=p1->next;
}
if(Class==p1->Class)
{

printf("学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s ",p1->id,p1->name,p1->sex,p1->Class,p1->college);
gole++;
if(p1==head)
head=head->next;
else
{
p2->next=p1->next;//删除结点p1
free(p1);
}
}
else
printf("\nThere is no one that you have input!!!!!");
printf("请按任意键返回,谢谢合作");
getch();
find=find->next;
}
if(!gole)
printf("\n你输错了,没有删除任何信息!!!!");
else
printf("\n一共删除了%d条信息",gole);
return head;
}


MESSAGE *DeleteStuAll(MESSAGE *head)
{
int gole=0;
MESSAGE *p1=head,*p2=NULL;
if(p1==NULL)
printf("你没有信息,不需要删除!!!");
while(p1!=NULL)
{
p2=p1;
p1=p1->next;
free(p1);
gole++;
}
printf("你一共删除了%d条信息",gole);
return p1;
}


MESSAGE *Change(MESSAGE *p)
{
int count=0;
char answer=0;
int choose=0;//思考修改系统的扩充功能:如何能够一次修改多个信息,达到不定项选择的目的
printf("\n学号:%d 姓名:%s 性别:%s 班级:%d 学院:%s ",p->id,p->name,p->sex,p->Class,p->college);
iteration1:
printf("\n你 %s 修改哪些信息??",count==0?"想":"还想");
fflush(stdin);
printf("\n1.学号 2.姓名 3.性别 4.班级 5.学院 6.返回");
scanf("%d",&choose);
fflush(stdin);
switch(choose)
{
case 1:
printf("Please input the new id:");
scanf("%d",&p->id);fflush(stdin);
count++;
printf("\nDo you want to change again???(y or n)");
scanf(" %c",&answer);fflush(stdin);
if(tolower(answer)=='y')
goto iteration1;
break;
case 2:
printf("Please input the new name:");
scanf("%s",p->name);fflush(stdin);
count++;
printf("\nDo you want to change again???(y or n)");
scanf(" %c",&answer);fflush(stdin);
if(tolower(answer)=='y')
goto iteration1;
break;
case 3:
printf("Please input the new sex:");
scanf("%s",p->sex);fflush(stdin);
count++;
printf("\nDo you want to change again???(y or n)");
scanf(" %c",&answer);fflush(stdin);
if(tolower(answer)=='y')
goto iteration1;
break;
case 4:
printf("Please input the new class:");
scanf("%d",&p->Class);fflush(stdin);
count++;
printf("\nDo you want to change again???(y or n)");
scanf(" %c",&answer);fflush(stdin);
if(tolower(answer)=='y')
goto iteration1;
break;
case 5:
printf("Please input the new college:");
scanf("%s",p->college);fflush(stdin);
count++;
printf("\nDo you want to change again???(y or n)");
scanf(" %c",&answer);fflush(stdin);
if(tolower(answer)=='y')
goto iteration1;
break;
case 6:
//思考如何返回上一层菜单的代码?调用函数
break;
}
return p;
}


void SearchStuMarkMenu(MARK *top)
{
int choose=0;
int id=0;
int i=0;int j=0;
int gole=0;
char name[20];
MARK *p1=top,*find=top;
MARK *p2=NULL;
fflush(stdin);
printf("\n1.按学号查询 2.按姓

名查询 3.返回");//思考:将case1和case 2的查询代码再做成一个函数:有个问题,查学号时需要传递top和id,查姓名需要传递top和name,这是2个类型的参数,如何能在
scanf("%d",&choose); //一个函数中????
switch(choose)
{
case 1:
printf("请输入要查询的学号:");
fflush(stdin);
scanf("%d",&id);
if(find==NULL)
printf("这里没有信息,请先添加!!!");
while(find!=NULL)
{
if(id==find->id)
{
gole++;
printf("\n学号:%d 姓名:%s ",find->id,find->name);
for(i=0;iprintf("\n%s:%.2f",find->sub[i].subname,find->sub[i].score);
printf("\n总分:%.4f",find->total);
break;
}
find=find->next;
}
if(gole==0)
printf("您输入的学号有误:");
break;
case 2:
printf("请输入您要查询的姓名:");
fflush(stdin);
gets(name);
while(find!=NULL)
{
if(strcmp(name,find->name)==0)
{
gole++;
printf("学号:%d 姓名:%s\n",find->id,find->name);
for(i=0;iprintf("%s:%.2f\n",find->sub[i].subname,find->sub[i].score);
printf("\n总分:%.4f\n",find->total);
break;
}
find=find->next;
if(gole==0)
printf("您输入的姓名有误!!!!");
}
break;
case 3:
//思考返回上一菜单的代码!!!调用函数
break;
}
}


MARK *AddStuMark(MARK *top)
{
int i=0;
MARK *p1=MAR,*p2=NULL;
printf("请输入学号:");
fflush(stdin);
scanf("%d",&p1->id);
printf("请输入姓名:");
fflush(stdin);
gets(p1->name);
p1->total=0;
for(i=0;i{
printf("\n请输入subname:");
fflush(stdin);
gets(p1->sub[i].subname);
printf("\n请输入score:");
fflush(stdin);
scanf("%f",&p1->sub[i].score);//问题竟然是score应该是float 我却粗心写成了%d
p1->total+=p1->sub[i].score;
}
p1->next=NULL;
if(top==NULL)
top=p1;
else
{
p2=p1; //将p1放至首位
p1->next=top;
top=p2;
}
return top;
}


MARK *DeleteStuMark(MARK *top)
{
int id=0;int gole=0;int i=0;
char name[20];
int choose=0;
char answer=0;
MARK *find=top,*p1=NULL;
if(find==NULL)
printf("没有任何可删除的信息!!!");
printf("\n1.按姓名删除 2.按学号删除");//也思考下:是否能将删除的过程作成一个函数,相同的问题:传入的参数怎么选择,返回的值又设定为那个?????
fflush(stdin);
scanf("%d",&choose);
switch(choose)
{
case 1:
printf("请输入你要删除的人的姓名:");
fflush(stdin);
gets(name);
while(find!=NULL)
{
if(strcmp(name,find->name))
{
gole++;
printf("学号:%d 姓名:%s\n",find->id,find->name);
for(i=0;iprintf("%s:%.2f\n",find->sub[i].subname,find->sub[i].score);
printf("\n总分:%.4f\n",find->total);
break;
}
p1=find;
fi

nd=find->next;
}
if(find!=NULL)
{
printf("\n你确定要删除以上信息???(y or n)");
fflush(stdin);
scanf("%c",&answer);
if(tolower(answer)=='y')
{
if(find==top)
{
top=top->next;
free(find);
}
else
{
p1->next=find->next;
free(find);
}
printf("\n已经成功删除以上信息!!!");//思考这句话为什么要在if里面了,嘿嘿!!!
}
}
else
printf("\n这里没有你要删除的人,请便");
break;
case 2:
printf("\n请输入你要删除的人的学号!!");
fflush(stdin);
scanf("%d",&id);
while(find!=NULL)
{
if(id==find->id)
{
gole++;
printf("学号:%d 姓名:%s\n",find->id,find->name);
for(i=0;iprintf("%s:%.2f\n",find->sub[i].subname,find->sub[i].score);
printf("\n总分:%.4f\n",find->total);
break;
}
p1=find;
find=find->next;
}
if(find!=NULL)
{
printf("\n你确定要删除以上信息??(y or n)");
fflush(stdin);
scanf("%c",&answer);
if(tolower(answer)=='y')
{
if(find==top)
top=top->next;
else
{
p1->next=find->next;//删除一个节点
free(find);
}
printf("\n您已成功删除以上信息!!!");
}
}
else
printf("\n你的输入有误,请三思:");
break;
}
return top;
}


MARK *ChangeStuMark(MARK *top)//有个问题:如果用一个函数来表达,每次只能修改一个,似乎可以用do while 来解决这个问题!!!
{
int id=0;int choose=0;int choose1=0;int choose2=0;int i=0;
char name[20];char answer=0;int count=0;char answer1=0;
MARK *find=top,*p1=NULL;
if(find==NULL)
printf("没有任何信息可供修改,请先添加");
do
{
printf("\n1.按学号查询并修改 2.按姓名查询并修改");
fflush(stdin);
scanf("%d",&choose);
switch(choose)
{
case 1:
while(find!=NULL)
{
if(id==find->id)
{
printf("学号:%d 姓名:%s\n",find->id,find->name);
for(i=0;iprintf("%s:%.2f\n",find->sub[i].subname,find->sub[i].score);
printf("\n总分:%.4f\n",find->total);
break;
}
p1=find;
find=find->next;
}
if(find!=NULL)
find=ChangeMark(find);
else
printf("\n您的输入有误,查无此人");
break;
case 2:
while(find!=NULL)
{
if(strcmp(name,find->name)==0)
{
printf("学号:%d 姓名:%s\n",find->id,find->name);
for(i=0;iprintf("%s:%.2f\n",find->sub[i].subname,find->sub[i].score);
printf("\n总分:%.4f\n",find->total);
break;
}
find=find->next;
}
if(find!=NULL)
find=ChangeMark(find);
else
printf("\n您的输入有误,查无此人");
break;
}
printf("\nDo you want to search again and change??(y or n)");
fflush(stdin);
scanf("%c",&answer);
}while(t

olower(answer)=='y');
return top;
}


MARK *ChangeMark(MARK *find)//以后要小心啊,这里少写一个字母,害我查了好久的错
{
int choose1=0;int count=0;char answer1=0;
int i=0,choose2=0;
change:
printf("你%s修改什么??1.学号id 2.姓名name 3.学科成绩 ",count==0?"想":"还想");//注意哈,在修改学科成绩的时候牵扯着总分也要被改变,这个已解决,Oh yeah!!
fflush(stdin);
scanf("%d",&choose1);
fflush(stdin);
switch(choose1)
{
case 1:
printf("Please input the new id:");
scanf("%d",&find->id);
count++;
printf("Do you want to change again??(y or n)");
fflush(stdin);
scanf("%c",&answer1);
if(tolower(answer1)=='y')
goto change;
break;
case 2:
printf("Please input the new name:");
gets(find->name);
count++;
printf("Do you want to change again??(y or n)");
fflush(stdin);
scanf("%c",&answer1);
if(tolower(answer1)=='y')
goto change;
break;
case 3:
printf("\n你想修改哪一科的成绩??(1,2,3,4,5):");
scanf("%d",&choose2);
fflush(stdin);
count++;
i=choose2-1;
find->total-=find->sub[i].score;
printf("\n请输入第%d科的新成绩:",choose2);
scanf("%d",find->sub[i].score);
find->total+=find->sub[i].score;
printf("Do you want to change again??(y or n)");
fflush(stdin);
scanf("%c",&answer1);
if(tolower(answer1)=='y')
goto change;
break;
}
return find;
}


MESSAGE *ReadFileStu(MESSAGE *head)
{
MESSAGE *add=NULL,*p1=NULL;
FILE *pfile=NULL;
fflush(stdin);
char *filename=(char *)malloc(50*sizeof(char ));
printf("请输入你想读取的文件名:");
gets(filename);
fflush(stdin);
strcat(filename,".txt");
if(!(pfile=fopen(filename,"r")))
{
printf("出错了!!!!!");
exit(1);
}
else
{
while(!feof(pfile))
{
add=MES;
if(!add)
{
printf("\nThere is no more memory for add");
exit(1);
}
printf("姓名 性别 学号 班级 学院 \n");//BUG:程序读取显示时会出现乱码,不知为何? 发现原因:保存文件时,读取文件时的各项没有对应起来,造成出错
fscanf(pfile,"%s%s%d%d%s",add->name,add->sex,&add->id,&add->Class,add->college);
printf("\n%s %s %d %d %s ",add->name,add->sex,add->id,add->Class,add->college);
p1=add; //思考:如果这样:add->next=head;head=add;add=add->next;这几个语句是什么效果呢????
add->next=head;
head=p1;//这三句代码把add放到了链表的第一位
}
fclose(pfile);
free(filename);
printf("\n读取信息成功!!");
}
return head;
}


MARK *ReadFileStuMark(MARK *top)
{
char *filename=(char *)malloc(100*sizeof(char ));
FILE *pfile=NULL;
MARK *add=NULL;
MARK *p1=NULL;
printf("\n请输入你想读取的文件名:");
fflush(stdin);
gets(fil

ename);
strcat(filename,".txt");
if(!(pfile=fopen(filename,"r")))
{
printf("出错了,不能够打开此文件");
exit(1);
}
else
{
while(!feof(pfile))
{
add=MAR;
if(add==NULL)
{
printf("\nThere is no more memory for add!!!");
exit(1);
}
fscanf(pfile,"%s %d",add->name,&add->id);//问:能否实现这样不同类型的同时录入 答:应该可以的
printf("\n姓名:%s 学号:%d",add->name,add->id);
for(int i=0;i{
fscanf(pfile,"%s %f",add->sub[i].subname,&add->sub[i].score);
printf("%s %f",add->sub[i].subname,add->sub[i].score);
}
fscanf(pfile,"%f",&add->total);
printf("\n%f",add->total);
add->next=NULL;
}
if(top==NULL)
top=add;
else
{
p1=add;
add->next=top;
top=p1;
}
}
fclose(pfile);
free(filename);
return top;
}


void SaveFileStu(MESSAGE *head)
{
char *filename=(char *)malloc(100*sizeof(char));
FILE *pfile=NULL;
MESSAGE *p=head;
printf("\n请输入你想保存数据的文件名:");
fflush(stdin);
gets(filename);
strcat(filename,".txt");
if(!(pfile=fopen(filename,"a")))
printf("打开文件失败了吧!!!");
if(p==NULL)
printf("没有任何信息,请先添加!!!");
while(p!=NULL)
{
printf("姓名:%s 性别:%s 学号:%d 班级:%d 学院:%s",p->name,p->sex,p->id,p->Class,p->college);
fprintf(pfile,"%s %s %d %d %s",p->name,p->sex,p->id,p->Class,p->college);
p=p->next;
}
fclose(pfile);
free(filename);
printf("保存成功!!");
}


void SaveFileStuMark(MARK *top)
{
char *filename=(char *)malloc(100*sizeof(char));
FILE *pfile=NULL;
MARK *p=top;
int i=0;
printf("\n请输入你想要保存分数的文件名:");
fflush(stdin);
gets(filename);
strcat(filename,".txt");
if(!(pfile=fopen(filename,"a")))
printf("\n打开文件失败!!!");
if(top==NULL)
printf("\n这里没有任何信息,请先添加!!!");
while(p!=NULL)
{
printf("姓名:%s 学号:%d",p->name,p->id);
fprintf(pfile,"%s %d",p->name,p->id);
for(i=0;i{
printf("%s : %f ",p->sub[i].subname,p->sub[i].score);
fprintf(pfile,"%s %f",p->sub[i].subname,p->sub[i].score);//为什么这里没存储正确的信息呢???哎,又是格式转化符%f错用成%d了,晕啊
}
printf("\n总分:%f",p->total);
fprintf(pfile,"%f",p->total);
p=p->next;
}
fclose(pfile);
free(filename);
printf("\n您已成功保存!!!!");
}

相关文档
最新文档