/*
* 烟台大学计算机与控制工程学院
*文件名称:student
*作 者:郝环宇
*完成日期:2016年12月28日
*版 本 号:v1.0
*
*问题描述:学生成绩管理系统及开发
*
*输入描述:无
*程序输出:无
qq.cpp 源文件:
运行结果:
* 烟台大学计算机与控制工程学院
*文件名称:student
*作 者:郝环宇
*完成日期:2016年12月28日
*版 本 号:v1.0
*
*问题描述:学生成绩管理系统及开发
*
*输入描述:无
*程序输出:无
*/
qq.h 头文件:
#ifndef QQ_H_INCLUDED
#define QQ_H_INCLUDED
#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#include <stdlib.h>
#include<string.h>
typedef struct STUDENT
{
char studentNumber[10];/*学生学号*/
char studentName[20];/*学生姓名*/
char className[20];/*班级名称*/
float mark1;/*第1门成绩*/
float mark2;/*第2门成绩*/
float mark3;/*第3门成绩*/
struct STUDENT *next;
}STUDENT;
/*以下是函数声明*/
void ReadInfoFormFile(void);//从文件中读学生信息到链表中
void CreateHeadLink(void);//建立链表表头
void freeHeadLink(void);//s释放链表表头
STUDENT *MallocNode(void);//申请一个新结点,并将其初始化
void GetInformation(STUDENT *t); //取得用户输入的学生信息
void OutputInformation(void); //显示所有学生的信息
void DesplayInfoBystudentName(void); //根据用户输入的学生姓名显示该学生的信息
void DesplayInfoBystudentNumber(void); //根据用户输入的学生学号显示该学生的信息
void DesplayOneNode(STUDENT *t); //输出一个节点的内容
void InsertOneNode(STUDENT *t); //在链表的结尾处增加一个结点
void DeleteNodeBystudentNumber(void); //根据用户输入的学号删除该学生
void ChangeMarkByName(void); //根据输入的班级、姓名修改成绩
void ChangeMarkByNumber(void); //根据输入的学期、学号修改成绩
void SaveLinkToFile(void); //保存链表数据到文件中
void DesplayMarkSegment(void); //不及格学生成绩
void CompositorByTotalMark(void); //按平均成绩排序
void CompositorByNumber(void);//按学号排序
void Menu2(void); //查询菜单
void ChangeMark(void);//修改成绩菜单
void Compositor(void);//学生信息排序菜单
#endif // QQ_H_INCLUDED
#include "qq.h"
int main()
{
int data=1,choose;
CreateHeadLink(); //创建链表头
ReadInfoFormFile(); //读取保存的文件信息
while(data)
{
STUDENT *p;
printf(" ******欢迎进入学生成绩管理系统******\n\n");
printf(" ************请选择您的操作**********\n\n");
printf(" | 1 增加学生 |\n");
printf(" | 2 查询学生信息 |\n");
printf(" | 3 输出各班级学生成绩单 |\n");
printf(" | 4 删除学生 |\n");
printf(" | 5 修改学生成绩 |\n");
printf(" | 6 学生信息排序并输出学生信息 |\n");
printf(" | 7 显示不及格学生成绩 |\n");
printf(" | 8 保存所有学生信息到文件中 |\n");
printf(" | 9 退出操作 |\n\n");
printf(" ------------------------------------\n\n");
scanf("%d",&choose);/*取得用户的选择*/
switch(choose)
{
case 1:
p=MallocNode();/*先申请一个新结点*/
GetInformation(p);/*要求用户输入信息到新结点中*/
InsertOneNode(p);/*将新结点加到链表中*/
break;
case 2:
Menu2();//查询学生信息有姓名和学号查询方式
break;
case 3:
OutputInformation();/*显示所有学生的信息*/
break;
case 4:
DeleteNodeBystudentNumber();/*根据用户输入的学号删除该学生*/
break;
case 5:
ChangeMark();/*修改成绩*/
break;
case 6:
Compositor();/*学生信息排序*/
break;
case 7:
DesplayMarkSegment();/*显示不及格的学生成绩*/
break;
case 8:
SaveLinkToFile();/*保存数据*/
break;
case 9:
SaveLinkToFile();/*保存数据后再退出*/
freeHeadLink();
data=0;
break;
default:
printf("输入错误,请重新输入\n");
break;
}
}
return 0;
}
qq.cpp 源文件:
#include "qq.h"
STUDENT *headLink;/*链表表头指针*/
/************************************
函数功能:从文件中读学生信息到链表中
************************************/
void ReadInfoFormFile(void)
{
FILE *fp;
STUDENT *p;
fp=fopen("student.txt","r"); //打开student.txt
if(!fp)
{
printf("文件不存在\n");
return;
}
p=MallocNode(); // 调用新建节点初始化函数
while(fscanf(fp,"%s%s%s%f%f%f",p->studentNumber,p->studentName,p->className,&(p->mark1),&(p->mark2),&(p->mark3))>0)
{
InsertOneNode(p); //结尾增加节点
p=MallocNode(); //新建节点初始化
}
fclose(fp); //关闭student.txt
}
/************************************
函数功能:删除链表表头
************************************/
void Menu2(void)
{
int a;
printf(" 1.按姓名查询 \n");
printf(" 2.按学号查询 \n");
scanf("%d",&a);
switch(a)
{
case 1:
DesplayInfoBystudentName(); //调用按姓名查询并输出
break;
case 2:
DesplayInfoBystudentNumber(); //调用按学号查询并输出
break;
}
}
/************************************
函数功能:删除链表表头
************************************/
void freeHeadLink(void)
{
free(headLink);
}
/************************************
函数功能:建立链表表头
************************************/
void CreateHeadLink(void)
{
STUDENT *p;
p=(STUDENT*)malloc(sizeof(STUDENT));
headLink=p;
p->next=NULL; //头节点指向空
}
/************************************
函数功能:申请一个新结点,并将其初始化
************************************/
STUDENT *MallocNode(void)
{
STUDENT *p;
int i;
p=(STUDENT*)malloc(sizeof(STUDENT));
if(p==NULL)
return NULL;
for(i=0;i<10;i++)
p->studentNumber[i]='\0';
for(i=0;i<20;i++)
p->studentName[i]='\0';
for(i=0;i<20;i++)
p->className[i]='\0';
p->mark1=0.0;
p->mark2=0.0;
p->mark3=0.0;
p->next=NULL;
return p;
}
/************************************
函数功能:取得用户输入的学生信息
************************************/
void GetInformation(STUDENT *t)
{
printf("请输入学生学号:\n");
scanf("%s",t->studentNumber);
printf("请输入学生姓名:\n");
scanf("%s",t->studentName);
printf("请输入该生所在班级:\n");
scanf("%s",t->className);
printf("请输入第1门成绩:\n");
scanf("%f",&(t->mark1));
printf("请输入第2门成绩:\n");
scanf("%f",&(t->mark2));
printf("请输入第3门成绩:\n");
scanf("%f",&(t->mark3));
printf("增加成功\n");
}
/************************************
函数功能:在链表的结尾处增加一个结点
************************************/
void InsertOneNode(STUDENT *t)
{
STUDENT *p;
p=headLink;
while(p->next) //当指针指向不为空时
{
p=p->next;
}
p->next=t; //当前指针指向t节点
}
/************************************
函数功能:根据用户输入的学生姓名
显示该学生的信息
************************************/
void DesplayInfoBystudentName(void)
{
STUDENT *p;
char studentName[20];
char flag=0; //定义一个变量记录是否存在该姓名
p=headLink->next; //p为头节点的下一个指向
printf("请输入学生姓名:\n");
scanf("%s",studentName);
while(p)
{
if(strcmp(p->studentName,studentName)==0)
{
printf("学号\t姓名\t班级\t成绩1\t成绩1\t成绩3\t总成绩\t平均成绩\n\n");
DesplayOneNode(p); // 显示当前节点的各项信息
flag=1;
}
p=p->next;
}
if(!flag)
printf("不存在姓名为 %s 的学生\n",studentName);
}
/************************************
函数功能:根据用户输入的学生学号
显示该学生的信息
************************************/
void DesplayInfoBystudentNumber(void)
{
STUDENT *p;
char studentNumber[20];
char flag=0;
p=headLink->next;
printf("请输入学生学号:\n");
scanf("%s",studentNumber);
while(p)
{
if(strcmp(p->studentNumber,studentNumber)==0)
{
printf("学号\t姓名\t班级\t成绩1\t成绩1\t成绩3\t总成绩\t平均成绩\n\n");
DesplayOneNode(p);
flag=1;
break;
}
p=p->next;
}
if(!flag)
printf("不存在学号为 %s 的学生\n",studentNumber);
}
/************************************
函数功能:输出一个结点的信息
************************************/
void DesplayOneNode(STUDENT *t)
{
printf("%s\t",t->studentNumber);
printf("%s\t",t->studentName);
printf("%s\t",t->className);
printf("%.2f\t",t->mark1);
printf("%.2f\t",t->mark2);
printf("%.2f\t",t->mark3);
printf("%.2f\t",t->mark1+t->mark2+t->mark3);
printf("%.2f\t\n",(t->mark1+t->mark2+t->mark3)/3);
}
/************************************
函数功能:根据用户输入的学号
删除该学生
************************************/
void DeleteNodeBystudentNumber(void)
{
char studentNumber[10];
STUDENT *p,*q; //定义p、q指针分别指向前一节点和当前节点
char flag=0; //定义一个变量记录是否存在该学号
printf("请输入要删除的学生学号:");
scanf("%s",studentNumber);
p=headLink;
q=headLink->next;
while(q)
{
if(strcmp(q->studentNumber,studentNumber)==0)
{
p->next=q->next; //前一节点指向当前节点的下一节点,断开当前节点
free(q); //释放当前节点
flag=1; //flag为1时代表遍历到该学号
break;
}
p=p->next; //前一节点后移
q=q->next; //当前节点后移
}
if(!flag)
{
printf("不存在该学号的学生\n");
return;
}
printf("成功删除\n");
}
/************************************
函数功能:显示所有学生的信息
************************************/
void OutputInformation(void)
{
STUDENT *p;
p=headLink->next;
if(p==NULL)
{
printf("现在没有学生信息,请先输入学生信息\n\n");
return;
}
printf("学号\t姓名\t班级\t成绩1\t成绩1\t成绩3\t总成绩\t平均成绩\n\n");
while(p)
{
DesplayOneNode(p); //显示当前学号的各项信息
p=p->next;
}
}
/************************************
函数功能:
修改成绩
************************************/
void ChangeMark(void)
{
int a;
printf(" 1.按班级、姓名修改 \n");
printf(" 2.按学期、学号修改 \n");
scanf("%d",&a);
switch(a)
{
case 1:
ChangeMarkByName();
break;
case 2:
ChangeMarkByNumber();
break;
default:
printf("没有该项功能\n");
break;
}
}
/************************************
函数功能:根据输入的班级、姓名
修改成绩
************************************/
void ChangeMarkByName(void)
{
STUDENT *p;
char a[5];
char studentName[20];
char flag=0;
float mark1,mark2,mark3;
p=headLink->next;
printf("请输入学生班级:\n");
scanf("%d",&a);
printf("请输入学生姓名:\n");
scanf("%s",studentName);
while(p)
{
if(strcmp(p->studentName,studentName)==0 && strcmp(p->className,a)==0)
{
printf("请输入新的第1门成绩:\n");
scanf("%f",&mark1);
printf("请输入新的第2门成绩:\n");
scanf("%f",&mark2);
printf("请输入新的第3门成绩:\n");
scanf("%f",&mark3);
p->mark1=mark1;
p->mark2=mark2;
p->mark3=mark3;
flag=1;
printf("修改成功\n");
break;
}
p=p->next;
}
if(!flag)
printf("不存在班级为 %d,姓名为 %s 的学生\n",&a,studentName);
}
/************************************
函数功能:根据输入的学号
修改成绩
************************************/
void ChangeMarkByNumber(void)
{
STUDENT *p;
char b[5];
char studentNumber[20];
char flag=0;
float mark1,mark2,mark3;
p=headLink->next;
printf("请输入学生学号:\n");
scanf("%s",studentNumber);
while(p)
{
if(strcmp(p->studentNumber,studentNumber)==0) //名字一样时执行
{
printf("请输入新的第1门成绩:\n");
scanf("%f",&mark1);
printf("请输入新的第2门成绩:\n");
scanf("%f",&mark2);
printf("请输入新的第3门成绩:\n");
scanf("%f",&mark3);
p->mark1=mark1;
p->mark2=mark2;
p->mark3=mark3;
flag=1;
printf("修改成功\n");
break;
}
p=p->next;
}
if(!flag)
printf("对不起,不存在学期为 %s 的学生\n",studentNumber);
}
/************************************
函数功能:保存链表数据到文件中
************************************/
void SaveLinkToFile(void)
{
STUDENT *p;
FILE *fp;
p=headLink->next;
if(p==NULL)
{
printf("现在没有学生信息,请先输入学生信息\n\n");
return;
}
fp=fopen("student.txt","w+");
if(!fp)
{
printf("文件不存在\n");
return;
}
while(p)
{ //将链表内的数据输出到stdent.txt中
fprintf(fp,"%s %s %s %f %f %f\n",p->studentNumber,p->studentName,p->className,p->mark1,p->mark2,p->mark3);
p=p->next;
}
printf("保存成功。 \n");
fclose(fp);
}
/************************************
函数功能:不及格学生成绩
************************************/
void DesplayMarkSegment(void)
{
STUDENT *p;
int count=0;
p=headLink->next;
printf("60分以下(不及格)的学生成绩如下:\n");
printf("学号\t姓名\t班级\t成绩1\t成绩1\t成绩3\t总成绩\t平均成绩\n\n");
while(p)
{
if((6>((int)(p->mark1/10)))||(6>((int)(p->mark2/10)))||(6>((int)(p->mark3/10))))/*只要有一科不及格就认为该生不及格*/
{
count++;
DesplayOneNode(p);
}
p=p->next;
}
printf ("不及格的学生一共有%d人\n",count);
}
/************************************
函数功能:排序
************************************/
void Compositor(void)
{
int a;
printf(" 1.按平均成绩排序 \n");
printf(" 2.按学号排序 \n");
scanf("%d",&a);
switch(a)
{
case 1:
CompositorByTotalMark();
break;
case 2:
CompositorByNumber();
break;
default:
printf("没有该项功能\n");
break;
}
}
/************************************
函数功能:按平均成绩排序
************************************/
void CompositorByTotalMark(void)
{
STUDENT exchange,*r,*p,*q;
r=headLink->next;
if(r==NULL)
{
printf("现在还没学生信息,请先输入学生信息\n");
return;
}
while(r)/*两层while循环实现排序*/
{
p=r;
q=r->next;
while(q)
{
if((q->mark1+q->mark2+q->mark3)>(p->mark1+p->mark2+p->mark3))
{
strcpy(exchange.studentNumber,q->studentNumber);/*先复制q结点信息到exchange*/
strcpy(exchange.studentName,q->studentName);
strcpy(exchange.className,q->className);
exchange.mark1=q->mark1;
exchange.mark2=q->mark2;
exchange.mark3=q->mark3;
strcpy(q->studentNumber,p->studentNumber);/*再复制p结点信息到q*/
strcpy(q->studentName,p->studentName);
strcpy(q->className,p->className);
q->mark1=p->mark1;
q->mark2=p->mark2;
q->mark3=p->mark3;
strcpy(p->studentNumber,exchange.studentNumber);/*最后复制exchange结点信息到p*/
strcpy(p->studentName,exchange.studentName);
strcpy(p->className,exchange.className);
p->mark1=exchange.mark1;
p->mark2=exchange.mark2;
p->mark3=exchange.mark3;
}
q=q->next;
}
r=r->next;
}
OutputInformation();
}
/************************************
函数功能:按学号排序
************************************/
void CompositorByNumber(void)
{
STUDENT exchange,*r,*p,*q;
r=headLink->next;
if(r==NULL)
{
printf("现在还没学生信息,请先输入学生信息\n");
return;
}
while(r)/*两层while循环实现排序*/
{
p=r;
q=r->next;
while(q)
{
if(strcmp(q->studentNumber,p->studentNumber)<0)
{
strcpy(exchange.studentNumber,q->studentNumber);/*先复制q结点信息到exchange*/
strcpy(exchange.studentName,q->studentName);
strcpy(exchange.className,q->className);
exchange.mark1=q->mark1;
exchange.mark2=q->mark2;
exchange.mark3=q->mark3;
strcpy(q->studentNumber,p->studentNumber);/*再复制p结点信息到q*/
strcpy(q->studentName,p->studentName);
strcpy(q->className,p->className);
q->mark1=p->mark1;
q->mark2=p->mark3;
q->mark3=p->mark3;
strcpy(p->studentNumber,exchange.studentNumber);/*最后复制exchange结点信息到p*/
strcpy(p->studentName,exchange.studentName);
strcpy(p->className,exchange.className);
p->mark1=exchange.mark1;
p->mark2=exchange.mark2;
p->mark3=exchange.mark3;
}
q=q->next;
}
r=r->next;
}
OutputInformation();
}
运行结果: