C语言学生成绩管理系统(单向链表)
玛丽莲梦兔
976次浏览
2020年08月01日 06:04
最佳经验
本文由作者推荐
双韵母-翁姑
本系统实现了学生管理系统的数据新建、插入、删除、遍历、保存到文件、文件读取、数据排序、数据销毁等操作;
*************************************************************************************/
/*************************************************************************************/
头文件my.h
/*************************************************************************************/
#include
#include
#include
#include
#define N 3
int num;
typedef struct learn
{ //成绩结构
int score[N]; //各门课成绩
int sum; //总分
float ave; //平均分
int order; //名次
}Learn;
typedef struct stu
{ //学生结构体
char no[10]; //学号
char name[20]; //姓名
char sex; //性别
int age; //年龄
Learn success; //成绩
struct stu *next; //只想后继结点的指针
} Student;
//data_ctrl.c
Student *Creatstu(); //新建学生成绩链表
void Insertnode(Student *head); //插入新的学生数据
Student *Deletenode(Student *head); //删除某条数据
void Modifystuinfo(Student *head); //修改链表数据
Student *Deletenode(Student *head); //删除某个节点
Student *DestoryList(Student *L); //销毁链表
//sort.c
Student *Searchbyno(Student *head,char *no); //按照学号查找记录
void Searchbyname(Student *head,char *name); //按照姓名查找记录
Student *Copylist(Student *head); //复制链表,备份链表
Student *Sortbysum(Student *head); //按总分排序
Student *Sortbyno(Student *head); //按学号排序
//display.c
void Menushow(); //菜单显示
void Printinfo(Student *head); //打印学生数据
void Printsinglestu(Student *p); //按条件打印单条数据
//file_ctrl.c
Student *Readfile(); //------
void Savetofile(Student *head,char *filename);//fwrite保存学生信息到文件
void SavetoFile2(Student *head,char *filename);//fprintf保存学生信息到文件
//main.c
Student *Searchbyno(Student*head,char*no); //按照学号查找记录
/*************************************************************************************/
源文件main.c
/*************************************************************************************/
#include"my.h"
/*
基于单向链表的学生管理系统
按提示操作即可
*/
//数据结构在my.h定义
void Help()
{
printf("
---很无语,你不知道怎么操作---
");
}
/*========================
主函数
==========================*/
int main()
{
Student *head,*p;
char no[10],name[20];
int k;
head=NULL; //初始化链表
while(1)
{
system("cls"); //清屏
Menushow(); //显示菜单
printf("请根据菜单选择所需操作:");
while(scanf("%d",&k)!=1) //排除输入的字符合字符串
{
fflush(stdin);
printf("
---输入错误!---
");
printf("请根据菜单选择所需操作:");
}
fflush(stdin); //清空缓冲区,gets函数会将行末的回车符当作一个空行读入
switch(k)
{
case 0: Help();break; //帮助信息
case 1: head=Creatstu();break; //新建学生成绩链表
case 2: head=Readfile(); //读取文件
break;
case 3: printf("请输入要查找的学号:"); //按学号查询
gets(no); p=Searchbyno(head,no);
if(p!=NULL)
Printsinglestu(p);
else
printf("---未找到!---
");
break;
case 4: printf("请输入要查找的姓名:"); //按姓名查询
gets(name); Searchbyname(head,name);
break;
case 5: head=Sortbyno(head); //按学号排序
printf("---当前链表为:---
");
Printinfo(head);break;
case 6: head=Sortbysum(head); //按总分排序
printf("---当前链表为:---
");
Printinfo(head); break;
case 7: Insertnode(head);break; //插入新的数据
case 8: Modifystuinfo(head);break; //修改某条学生数据
case 9: head=Deletenode(head);Printinfo(head);break; //删除数据
case 10:system("cls");Printinfo(head);break; //打印学生所有信息
case 11:Savetofile(head,""); //fwrite方式写入存储,打开是乱码 //保存文件
SavetoFile2(head,""); //fprintf方式写入存储,打开可以正常显示
break;
case 12:head=DestoryList(head); break; //销毁链表
case 13:printf("
t==============================
");
printf("tt欢迎使用,再见");
printf("
t==============================
");exit(0); //退出
default: printf("
---输入错误!---
");break;
}
printf("
-----------------
");
printf("按任意键继续!");
getch(); //getch函数
的作用是从键盘只接受一个字符,而且并不把这个字符显示出来,也不用按下回车键就返回到调用函数。
}
return 0;
}
/*************************************************************************************/
源文件sort.c
/*************************************************************************************/
#include "my.h"
//按照学号查找记录
Student *Searchbyno(Student *head,char *no)
{
Student *p; //移动指针
p=head;
while(p!=NULL&&strcmp(p->no,no)!=0)
p=p->next; //移动指针,指向下一结点
return p;
}
//按照姓名查找记录
void Searchbyname(Student *head,char *name)
{
Student *p;
p=head;
while(p!=NULL)
{
if(strcmp(p->name,name)==0)
Printsinglestu(p); //输出学生信息
p=p->next;
}
if(p==NULL)
printf("---未找到!---
");
}
//复制链表,备份链表
Student *Copylist(Student *head)
{
Student *newlist,*s,*p;
int i=0,j;
while(head!=NULL)
{
i++;
s=(Student *)malloc(sizeof(Student));
strcpy(s->no,head->no);
strcpy(s->name,head->name);
s->sex=head->sex;
s->age=head->age;
for(j=0;j
s->=head->;
s->=head->;
s->=head->;
if(i==1)
{
newlist=s;
s->next=NULL;
}
else p->next=s;
p=s;
head=head->next;
}
p->next=NULL;
printf("---复制链表成功!---
");
return newlist;
}
/*
===============
按总分排序(降序排序:大---->小)
===============
*/
Student *Sortbysum(Student *head)
{
char ch;
Student *first,*tail,*p_front,*max,*p,*copyhead;
//*first; /*排列后有序链的表头指针*/
//*tail; /*排列后有序链的表尾指针*/
//*p_front; /*保留键值更小的节点的前驱节点的指针*/
//*max; /*存储最小节点*/
//*p; /*当前比较的节点*/
int i;
system("cls");
if(head==NULL)
{
printf("---空链表!请先新建链表或文件读取---
");
return head;
}
//先复制链表,以作备份
copyhead=Copylist(head);
/////
first=NULL;
while(head!=NULL) /*在链表中找键值最大的节点。*/
{
for(p=head,max=head;p->next!=NULL;p=p->next) /*循环遍历链表中的节点,找出此时最大的节点。*/
{
if(p->next-> > max->) /*找到一个比当前max大的节点。*/
{
p_front=p; //保存最小节点的前一个节点
max=p->next; //保存此时链表最大的节点值
}
}
/*将得到的值放入有序链表中;*/
if(first==NULL) /*第一次找到键值最大的节点。*/
{
first=max;
tail=max;
}
else /*有序链表中已经有节点*/
{
tail->next=max;
tail=max;
}
/*第二件事,原链表指针后移*/
if(max==head) /*如果找到的最小节点是第一个节点*/
head=head->next;
else /*如果不是第一个节点*/
p_front->next = max->next; /*跳过找到的当前最小节点max,指向下一个节点*/
}
if(first!=NULL)//有序链表的尾节点要指向NULL
tail->next=NULL;
//完成总分排序
i=0;
p=first;
while(p!=NULL) //存储总分排名
{
i++;
p->=i;
p=p->next;
}
printf("---排序成功!排序如下---
");
Printinfo(first);
printf("
");
printf("---是否将排序后的链表覆盖原链表?(默认否)(Y/N)---
");
ch=getchar();
if(ch=='Y'||ch=='y')
{
printf("---链表已覆盖,当前链表为按总分降序的数据---
");
//savetofile(head,"");
return first;
}
else
{
printf("---链表未覆盖---
");
//savetofile(head,"");
return copyhead;
}
}
/*
=====================
按学号排序(降序:小-->大)
=====================
*/
Student *Sortbyno(Student *head)
{
char ch;
Student *first,*tail,*p_front,*min,*p,*copyhead;
if(head==NULL)
{
printf("---空链表!请先新建链表或文件读取---
");
return head;
}
//先复制链表,以作备份
copyhead=Copylist(head);
/////
first=NULL;
while(head!=NULL)
{
for(p=head,min=head;p->next!=NULL;p=p->next)
{
if(strcmp(p->next->no ,min->no)<0)//p->next->name比较小
{
p_front=p; //保存最小节点的前一个节点
min=p->next; //保存此时链表最小的节点值
}
}
/*将得到的值放入有序链表中;*/
if(first==NULL)
{
first=min;
tail=min;
}
else /*有序链表中已经有节点*/
{
tail->next=min;
tail=min;
}
/*原链表指针后移*/
if(min==head)
head=head->next;
else
p_front->next = min->next;
}
if(first!=NULL)
tail->next=NULL;
//完成总分排序
system("cls");
printf("---排序成功!排序如下--
");
Printinfo(first);
printf("---是否将排序后的链表覆盖原链表?(默认否)(Y/N)---
");
ch=getchar();
if(ch=='Y'||ch=='y')
{
printf("---链表已覆盖,当前链表为按总分降序的数据---
");
//savetofile(head,"");
return first;
}
else
{
printf("---链表未覆盖---
");
//savetofile(head,"");
return copyhead;
}
}
/*************************************************************************************/
源文件data_ctrl.c
/*************************************************************************************/
#include"my.h"
//新建学生链表----
Student *Creatstu()
{
Student *head;
Student *s,*p;
char ch;int i;
num=0;
head=NULL;
system("cls");
do
{
num=num+1; //计数
fflush(stdin); //清空缓冲区,gets函数会将行末的回车符当作一个空行读入
s=(Student *)malloc(sizeof(Student));
printf("请输入要插入学生的信息
");
printf("请输入学生的学号:");
gets(s->no);
printf("请输入学生的姓名:");
gets(s->name);
printf("请输入学生的性别:");
s->sex=getchar();
printf("请输入学生的年龄:");
scanf("%d",&s->age);
printf("请输入学生的三门课程成绩:");
scanf("%d",&s->[0]);
scanf("%d",&s->[1]);
scanf("%d",&s->[2]);
s->=0;
s->=0;
for(i=0;i
s->=(float)s->/N;
if(num==1)
{
head=s;
s->next=NULL;
}
else p->next=s;
p=s;
printf("是否继续输入学生记录(Y/N):");
fflush(stdin);//
ch=getchar();
}
while(ch=='Y'||ch=='y');
p->next=NULL;///////
printf("--Success!--已新建%d个数据---
",num);
return head;
}
//插入新的数据
void Insertnode(Student *head)
{
char no[10],ch;int i;
Student *p,*q,*r,*t;
q=(Student *)malloc(sizeof(Student));
p=head; //先将p指向链表NULL前一个数据
while(p->next!=NULL)
p=p->next;
system("cls"); //清屏
printf("请输入要插入的学生的信息
");
printf("请输入学生的学号:");
fflush(stdin); //清空缓冲区,gets函数会将行末的回车符当作一个空行读入
gets(q->no);
while(head!=NULL)
{
r=Searchbyno(head,q->no);
if(r==NULL) { break; }
else
{
printf("---该学号已经存在,请重新输入!---
");
printf("请重新输入学生的学号:");
gets(q->no);
}
}
printf("请输入学生的姓名:");
gets(q->name);
printf("请输入学生的性别:");
q->sex=getchar();
printf("请输入学生的年龄:");
scanf("%d",&q->age);
printf("请输入学生的三门课程成绩:");
scanf("%d",&q->[0]);
scanf("%d",&q->[1]);
scanf("%d",&q->[2]);
q->=0;
for(i=0;i
q->=(float)q->/N;
q->=0;
printf("是否默认将此学生信息插入到最后?(Y/N)
");
fflush(stdin); //清空缓冲区,gets函数会将行末的回车符当作一个空行读入
ch=getchar();
if(ch=='N'||ch=='n')
{
printf("输入要插入的学号(数据插到学号后)
");
fflush(stdin); //清空缓冲区,gets函数会将行末的回车符当作一个空行读入
gets(no);
t=Searchbyn
o(head,no); //判断这个数据的位置
if(t==NULL) //数据插到最后
{
printf("---没有找到需要插入的位置,新学生信息自动插入到最后!---
");
q->next=NULL;
p->next=q;
}
else //插到这个学号后面
{
printf("---已找到要插入的位置!---
");
q->next=t->next;
t->next=q;
printf("---已经插入指定位置---
");
}
}////////
else //默认插到最后
{
q->next=NULL;
p->next=q;
printf("---新学生信息已经自动插入到最后!---
");
}
num++;
printf("---共有%d个学生数据
---",num);
//手动保存或者自动保存savetofile(head,"");
}
//修改链表数据
void Modifystuinfo(Student *head)
{
char no[10];
Student *p;
int i;
system("cls");
printf("---所有学生数据如下---
");
Printinfo(head);
printf("
");
if(head==NULL)
return;
printf("请输入要修改学生信息的学号:");
gets(no);
p=Searchbyno(head,no);
if(p==NULL)
{
printf("---没有找到该学生!---
");
}
else
{
printf("学号t姓名t性别t年龄t课程成绩
");
printf("%st%st%ct%dt%3d%3d%3d
",p->no,p->name,p->sex,p->age,
p->[0],p->[1],p->[2]);
printf("请输入修改后的学生信息:
");
printf("请输入新学号:");
gets(p->no);
printf("请输入新姓名:");
gets(p->name);
printf("请输入新性别:");
p->sex=getchar();
printf("请输入新年龄:");
scanf("%d",&p->age);
printf("请输入新三门课程成绩:");
scanf("%d",&p->[0]);
scanf("%d",&p->[1]);
scanf("%d",&p->[2]);
for(i=0;i
p->=(float)p->/N;
printf("---Success!修改完成!----
");
}
//手动或自动保存 savetofile(head,"");
}
//删除节点
Student *Deletenode(Student *head)
{
Student *p1,*p2;
char no[10];
system("cls");
if(head==NULL)
{
printf("---空链表!请新建链表或文件读取---
");
return head;
}
printf("---所有学生信息如下:----
");
Printinfo(head);
printf("请输入要删除学生信息的学号:");
gets(no);
p1=head;
while(p1!=NULL&&strcmp(p1->no,no)!=0)//查找要删除的节点
{
p2=p1; //保存前一个节点
p1=p1->next;
}
if(strcmp(p1->no,no)==0)
{
if(p1==head) //删除表头
{
head=p1->next;
}
else //删除表中的节点
{
p2->next=p1->next;
}
printf("---已删除学号%s的信息----
",no);
num=num-1;
printf("---现在有%d个学生数据---
",num);
}
else
printf("---学号%s未找到---
",no);
return head;
}
//销毁链表
Student *DestoryList(Student *L)
{
Student *p;
int n=0;
if(L==NULL)//判断为空链表
{
printf("
---空链表!请新建或读取文件---
");
return NULL;
}
printf("
");
while(L)
{
p=L;
L=L->next;
free(p);
n++;
printf("---已销毁%d条数据---
",n);
}
printf("---Success!销毁完成---
");
return NULL;
}
/*************************************************************************************/
源文件file_ctrl.c
/*************************************************************************************/
#include"my.h"
//文件读取学生信息
Student *Readfile()
{
FILE*fp;
Student stu,*p,*q,*head;
int i=0;
head=NULL;
system("cls");
if((fp=fopen("","rb"))==NULL)
{
//printf("不能打开文件
");
printf("---文件没有被创建---
");
printf("---请新建链表后保存---
");
return NULL;
}
fread(&stu,sizeof(stu),1,fp);
num=0;
while(!feof(fp))
{
num++;
q=(Student*)malloc(sizeof(Student));
*q=stu;
if(i==0)
{
head=q;
q->next=NULL;
}
else p->next=q;
p=q;
fread(&stu,sizeof(stu),1,fp);
i++;
}
p->next=NULL;
fclose(fp);
printf("---共读取%d个学生信息---
",num);
printf("---读取文件成功!数据显示如下:---
");
printf("
");
Printinfo(head);
return head;
}
//保存成可视文本(fwrite写人显示的是乱码,fprintf写入显示的正常)
void SavetoFile2(Student *head,char *filename)
{
FILE *fp;
Student *p;
p=head;
if(head==NULL)
{
printf("---空链表!请新建链表---
");
return;
}
if((fp=fopen(filename,"wb"))==NULL)
{
printf("---不能打开文件---
");
return;
}
do
{
fprintf(fp,"%st%-5st%ct%dt%-5d%-5d%-5dt%dt%-8.2ft%d
",p->no,p->name,p->sex,p->age,
p->[0],p->[1],p->[2],
p->,p->,p->);
p=p->next;
}
while(p!=NULL);
printf("---文件已保存到---
");
printf("---打开可查看保存的数据---
");
fclose(fp);
}
//用fwrite保存,和读取文件时的fread对应
void Savetofile(Student *head,char *filename)
{
FILE *fp;
Student stu,*p;
p=head;
if(head==NULL)
{
printf("
---空链表!请新建链表---
");
return;
}
if((fp=fopen(filename,"wb"))==NULL)
{
printf("---不能打开文件---
");
return;
}
do
{
stu=*p;
fwrite(&stu,sizeof(stu),1,fp);
p=p->next;
}while(p);
printf("
---文件已保存到工程目录下的---
");
fclose(fp);
}
/*************************************************************************************/
源文件display.c
/*************************************************************************************/
#include"my.h"
//菜单显示
void Menushow()
{
printf("
t**************学生成绩管理系统***************
");
printf("
tt0
.帮助");
printf("
tt-----------------");
printf("
tt1.新建链表tt2.文件读取");
printf("
tt-----------------");
printf("
tt3.按学号查找tt4.按姓名查找");
printf("
tt-----------------");
printf("
tt5.按学号排序(升序)t6.按总分排序(降序)");
printf("
tt-----------------");
printf("
tt7.插入新的数据tt8.修改数据");
printf("
tt9.删除数据");
printf("
tt-----------------");
printf("
tt10.数据显示tt11.保存数据到本地文件");
printf("
tt12.销毁链表");
printf("
tt-----------------");
printf("
tt13.退出系统
");
printf("
tttttt--2014.10.03--
");
printf("
t*********************************************
");
}
//打印学生所有数据
void Printinfo(Student *head)
{
Student *p;
p=head;
if(p==NULL)
{
printf("---空链表---
");
printf("---请新建链表或文件读取---
");
}
else
{
printf("学号t姓名t性别t年龄t课程成绩t总成绩t平均成绩t名次
");
while(p!=NULL)/////////////////
{
printf("%st%-5st%ct%dt%-5d%-5d%-5dt%dt%-8.2ft%d
",p->no,p->name,p->sex,p->age,
p->[0],p->[1],p->[2],
p->,p->,p->);
p=p->next;
}
}
}
//符合条件的单个学生信息输出
void Printsinglestu(Student *p)
{
printf("
学号t姓名t性别t年龄t课程成绩t总成绩t平均成绩t名次
");
printf("%st%-5st%ct%dt%-5d%-5d%-5dt%dt%-8.2ft%d
",p->no,p->name,p->sex,p->age,
p->[0],p->[1],p->[2],p->,p->,p->);
}