
C语言程序设计实训2:基于链表的学生信息管理系统
目录1.实验内容2.实验要求3.功能结构图和算法流程图4.程序清单5.程序运行截图1.实验内容编写并调试程序,实现学校各专业班级学生信息的管理。要求一个工程下多个文件。main函数以单独的文件main.cpp存放。在头文件student.h中定义学生信息的结构体类型,包括:学号、姓名、专业、班级、3门成绩。要求同一班级的学生属于不同的专业,同一专业的学生属于不同的班级。全局类型的定义如下:#def
大胆相信我,我这科拿了满分嗷~
目录
1.实验内容
编写并调试程序,实现学校各专业班级学生信息的管理。要求一个工程下多个文件。main函数以单独的文件main.cpp存放。在头文件student.h中定义学生信息的结构体类型,包括:学号、姓名、专业、班级、3门成绩。要求同一班级的学生属于不同的专业,同一专业的学生属于不同的班级。
全局类型的定义如下:
#define N 12
struct Student{
char num[15];//学号
char name[15];//姓名
char major[10];//专业(computer,software,network)
int classNo;//班级(1-2)
int score[3];//3门课的成绩(0-2)
struct Student *next;//指向下一结点的指针
};
typedef struct Student STU;
2.实验要求
- main函数:以菜单形式将各项功能提供给用户,根据用户的选择,调用相应的函数。
- 定义函数STU *CreateList(char * filename):从二进制文件“studentInfo.dat”中依次读取12个学生的数据(在文件中学生信息按学号由低到高依次存放),建立带头结点(特殊结点,不放学生信息)的、有序的单链表(链表中各学生信息按学号由低到高依次存放), 返回表头指针。每次从文件中读一个学生的信息,并将该学生信息插入到链表的表尾。设置头结点的目的:在链表中第一个学生结点之前插入或者是删除第一个学生结点的时候不必做特殊处理)更灵活的方法:从文件中循环读数据时,根据当前学生信息的next成员的值,决定是否进行下次循环,如果next==NULL,则表明读到最后一个学生信息,循环结束。
- 定义函数void Output (STU *head):以指向链表头结点的指针为参数,将链表中所有学生的信息表格化输出。定义函数 void OutOneNode(STU *p): 输出参数所指的链表中一个结点的信息。
- STU *Max(STU *head):查找总成绩最高的学生,返回指向该学生结点的指针。
- 定义函数STU *Search_num(STU * head ,char *num ):查找指定学号的学生,返回指向该学生结点的指针。
- 定义函数 void InsertList(STU * head, STU stu ):将某个学生信息插入到链表中的相应位置,并保持此链表按学号的有序性。
- 定义函数void Delete_num(STU * head,char *num):从链表中删除指定学号的学生。
- 定义函数STU *Search_major _subject_score(STU *head, char *major, int subject , int grade ):查找某个专业的、某门课程的成绩小于某个分数的学生,返回指向该学生结点的指针。若假设只找到一个学生即可,则返回指向该学生的指针;若假设如果有多个学生都要找到,则需另建立一个链表,从堆中申请空间,将所有满足条件的学生信息拷贝过来,链接起来(不破坏原来的学生信息链表),返回该指向链表头的指针。
- 定义函数void Delete_ class _subject_score(STU *head, int classno, int subject, int grade):从链表中删除某个班级的、某门课程的成绩小于某个分数的学生。
- 定义函数Save(STU *head):将更新后的学生信息存入一个名字为“studentInfoNew.dat”的文件中。
除main函数和Output、OutOneNode函数外,其它函数中不允许有键盘输入和屏幕输出的操作。
功能说明:
- 从文件中读取信息:可以从任意的以struct Student结构体定义的文件中读取信息。即读取的信息能够自动判断数据读取结束。
- 显示链表中学生信息:可以任意时刻显示当前正在处理的链表中的信息。
- 总分最高:如果有相同总分的,要求能够显示出多个人的信息。
- 查找指定学号的学生信息。
- 输入学生信息,正确插入。
- 删除指定学号的学生信息:要求可以删除所有学生的信息。
- 按要求查找:能够把查询的结果另存为其他文件。
- 按班级和课程删除:要求能够删除所有人的信息。
- 保存:将当前的链表保存到指定的文件中。
- 挑战:按任意一门课程或者总分排序,能够保存。
测试用例一:
功能1,打开studentInfo.dat文件
功能2,显示12名学生信息
功能3,查找总分最高的学生
功能6,删除总分最高的学生之外的任意一名学生
功能5,输入一个小于第一个学生学号的学生,保证总分与最高的学生一样
功能3,查找总分最高的学生,输出的结果应该是两名学生
功能9,保存为max.dat文件
功能1,打开max.dat文件(文件中有两条数据)
功能2,显示学生信息。
测试用例二:
功能1,打开studentInfo.dat文件
功能7,查找computer专业,第一门课程,小于20分的学生信息
功能7,查找network专业,第二门课程,小于200分的学生信息
功能9,保存查询的结果为zhuanye.dat
功能1,打开zhuanye.dat
功能2,显示学生信息
功能6,执行多次,将学生的信息逐个删除,保留一个
功能9,保存文件
功能1,打开zhuanye.dat,插入1个学生信息。
测试用例三:
功能1,打开studentInfo.dat文件
功能2,显示12名学生信息
功能4,输入不存在的学生学号进行查找(提示:)
功能8,删除1班第一门课程小于100分的学生信息
功能9,保存当前链表为class.dat文件
功能1,打开class.dat文件
功能2,显示学生信息
功能8,将另外班级的所有学生依次删除
功能2,显示学生信息
功能9,保存文件为empty.dat(文件中数据为空)
功能1,打开文件empty.dat,插入1个学生信息,保存。
测试用例四:
功能7或者功能8的结果,保存文件sort.dat
功能1,打开sort.dat文件
功能2,显示信息
功能10,排序,保存。
3.功能结构图和算法流程图
系统功能结构图
函数Delete_ class _subject_score的算法流程图。
4.程序清单
此处为头文件代码
#ifndef __STUDENT_H__
#define __STUDENT_H__
#define N 12
struct Student{
char num[15];//学号
char name[15];//姓名
char major[10];//专业(computer,software,network)
int classNo;//班级(1-3)
int score[3];//3门课的成绩
struct Student *next;
};
typedef struct Student STU;
STU* Input();//输入学生信息
void Save(STU *head);//保存数据文件
void Store(STU *head);//保存无头数据文件
STU *CreateList(char *filename);//从文件中依次读取12个学生数据
void Output(STU *head);//以指向链表头结点的指针为参数,将链表中所有学生的信息表格化输出
void Outprintf(STU* head) ;//无头输出
void OutOneNode(STU *p);//输出参数所指的链表中一个结点的指针
STU *Max(STU *head);//查找总成绩最高的学生,返回指向该学生结点的指针
STU *Search_num(STU *head,char *num);//查找指定学号的学生,返回指向该学生结点的指针
void *Insert(STU *head,STU stu);//按学号排序插入学生信息
void *Delete(STU *head,char *num);//删除指定学号的信息
STU *Search_sub(STU *head,char *maj,int sub,int sco);//查找某个专业某门成绩小于某个分数的同学
void *Delete_sub(STU *head,int classNo,int sub,int sco);//删除某个班级某门成绩小于某个分数的同学
STU *Sort_big(STU *head);//将学生信息按照分数由高到低排序
#endif
此处为主函数部分代码
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include"student.h"
#include"fun.cpp"
#define len sizeof(STU)
char filename[15]; //文件名
STU *head,*newstuhead;//链表头结点
STU stu;//预存输入学生信息
STU *now;//链表当前结点
STU *p;//链表预存结点
char m[15];//学号
char maj[15];//专业
int n,sub,sco,classNo;
int main(){
while(1){
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");
printf("10.将学生信息按照分数由高到低排序\n");
printf("其他,退出系统\n");
scanf("%d",&n);
if(n<1||n>10)break;
switch(n){
case 1:
printf("请输入要查找的文件名:\n");
getchar();
gets(filename);
head=CreateList(filename);
printf("\n学号\t 姓名\t\t专业 \t班级 成绩1 成绩2 成绩3 \t\n");
Output(head);
break;
case 2:
printf("\n学号\t 姓名\t\t专业 \t班级 成绩1 成绩2 成绩3 \t\n");
Output(head);
break;
case 3:
printf("\n学号\t 姓名\t\t专业 \t班级 成绩1 成绩2 成绩3 \t\n");
Output(Max(head));
Save(Max(head));
break;
case 4:
now=head->next;
p=now;
printf("请输入要查找的学生学号:\n");
scanf("%s",m);
while (now != NULL&&strcmp(now->num,m)!=0) {
now = now->next;
}
if(now==NULL) printf("查无此人,请重新输入。\n");
else {
printf("\n学号\t 姓名\t\t专业 \t班级 成绩1 成绩2 成绩3 \t\n");
OutOneNode(Search_num(head,m));
}
break;
case 5:
getchar();
printf("请输入转入学生学号:");
scanf("%s",stu.num);
getchar();
printf("请输入转入学生姓名:");
scanf("%s",stu.name);
getchar();
printf("请输入转入学生专业:");
scanf("%s",stu.major);
printf("请输入转入学生班级:");
scanf("%d",&stu.classNo);
printf("请输入转入学生成绩1:");
scanf("%d",&stu.score[0]);
printf("请输入转入学生成绩2:");
scanf("%d",&stu.score[1]);
printf("请输入转入学生成绩3:");
scanf("%d",&stu.score[2]);
stu.next=NULL;
Insert(head,stu);
break;
case 6:
printf("请输入想要删除学生的学号:");
scanf("%s",m);
Delete(head,m);
break;
case 7:
printf("请输入想要查询的专业:");
scanf ("%s",maj);
printf("请输入查询科目:");
scanf("%d",&sub);
if(sub>3||sub<1) printf("无此科目,请重新输入。\n");
else{
printf("请输入分数线:");
scanf("%d",&sco);
if(Search_sub(head,maj,sub,sco)->next==NULL) printf("查无此人,请重新输入。\n");
else {
printf("\n学号\t 姓名\t\t专业 \t班级 成绩1 成绩2 成绩3 \t\n");
Outprintf(Search_sub(head,maj,sub,sco));
Store(Search_sub(head,maj,sub,sco));
}
}
break;
case 8:
printf("请输入想要查询的班级:");
scanf ("%d",&classNo);
if(classNo>3||classNo<1) printf("无此班级,请重新输入。\n");
else{
printf("请输入查询科目:");
scanf("%d",&sub);
if(sub>3||sub<1) printf("无此科目,请重新输入。\n");
else{
printf("请输入分数线:");
scanf("%d",&sco);
Delete_sub(head,classNo,sub,sco);
}
}
break;
case 9:
Save(head);
break;
case 10:
Sort(head);
break;
}
}
return 0;
}
定义函数:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include"student.h"
#define len sizeof(STU)
char filename[15]; //文件名
STU *head,*newstuhead;//链表头结点
STU stu;//预存输入学生信息
STU *now;//链表当前结点
STU *p,*temp;//链表预存结点
char m[15];//学号
char maj[15];//专业
int n,sub,sco,classNo;
void *Sort(STU *head){
p=head->next;
now=head;
temp=head;
while(p!=NULL){
while(p->next!=NULL){
if((p->score[0]+p->score[1]+p->score[2])<(p->next->score[0]+p->next->score[1]+p->next->score[2])){
strcpy(temp->num,p->num);
strcpy(temp->name,p->name);
strcpy(temp->major,p->major);
temp->classNo=p->classNo;
temp->score[0]=p->score[0];
temp->score[1]=p->score[1];
temp->score[2]=p->score[2];
strcpy(p->num,p->next->num);
strcpy(p->name,p->next->name);
strcpy(p->major,p->next->major);
p->classNo=p->next->classNo;
p->score[0]=p->next->score[0];
p->score[1]=p->next->score[1];
p->score[2]=p->next->score[2];
strcpy(p->next->num,temp->num);
strcpy(p->next->name,temp->name);
strcpy(p->next->major,temp->major);
p->next->classNo=temp->classNo;
p->next->score[0]=temp->score[0];
p->next->score[1]=temp->score[1];
p->next->score[2]=temp->score[2];
}
p=p->next;
}
p=now->next;
now=now->next;
}
}
void *Delete_sub(STU *head,int classNo,int sub,int sco){//删除某个班级某门成绩小于某个分数的同学
now=head->next;
p=head;
while(now!=NULL){
if(classNo==now->classNo&&(sco>(now->score[sub-1]))){
p->next=now->next;
now=p->next;
}
else {
p=p->next;
now=now->next;
}
}
}
STU *Search_sub(STU *head,char *maj,int sub,int sco){//查找某个专业某门成绩小于某个分数的同学
now=head;
STU *newstuhead,*newstu;//建立新符合要求的链表
newstu=(STU *)malloc(len);
int flag=0 ;
newstuhead=newstu;
while(now!=NULL){
if(strcmp(maj,now->major)==0&&(sco>(now->score[sub-1]))){
if(flag!=0){
newstu->next=(STU *)malloc(len);
newstu=newstu->next;
}
strcpy(newstu->num,now->num);
strcpy(newstu->name,now->name);
strcpy(newstu->major,now->major);
newstu->classNo=now->classNo;
newstu->score[0]=now->score[0];
newstu->score[1]=now->score[1];
newstu->score[2]=now->score[2];
flag++;
}
now=now->next;
}
newstu->next=NULL;
return newstuhead;
}
void *Delete(STU *head,char *num){//删除指定学号的信息
now=head;
while(now->next){
if(strcmp(num,now->next->num)!=0){
now=now->next;
}
else{
p=now->next->next;
now->next=p;
break;
}
}
if(now->next==NULL) printf("查无此人,请重新输入。\n");
else printf("删除成功!\n");
}
void *Insert(STU *head,STU stu){//按学号排序插入学生信息
STU *q;
now=head->next;
p=(STU *)malloc(len);
*p=stu;
if(strcmp(now->num,stu.num)>0){
p->next=now;
head->next=p;
}
else{
while(now->next!=NULL){
q=now->next;
if(strcmp(stu.num,now->num)>0&&strcmp(q->num,stu.num)>0){
p->next=q;
now->next=p;
break;
}
else now=now->next;
}
if(now->next==NULL){
now->next=p;
p->next=NULL;
}
}
}
STU *Max(STU *head){
p=head->next;
now=head;
STU *newstuhead,*newstu,*high;//建立新符合要求的链表
newstu=(STU *)malloc(len);
int flag=0 ,sum=0;
newstuhead=newstu;
while(p!=NULL){
if((p->score[0]+p->score[1]+p->score[2])>sum){
sum=p->score[0]+p->score[1]+p->score[2];
high=p;
}
p=p->next;
}
while(now!=NULL){
if((now->score[0]+now->score[1]+now->score[2])>=sum){
if(flag!=0){
newstu->next=(STU *)malloc(len);
newstu=newstu->next;
}
strcpy(newstu->num,now->num);
strcpy(newstu->name,now->name);
strcpy(newstu->major,now->major);
newstu->classNo=now->classNo;
newstu->score[0]=now->score[0];
newstu->score[1]=now->score[1];
newstu->score[2]=now->score[2];
flag++;
}
now=now->next;
}
newstu->next=NULL;
return newstuhead;
}
STU* CreateList(char* filename) {//从文件中依次读取12个学生数据
FILE *fp;
if((fp=fopen(filename,"rb"))==NULL){
printf("Wrong.");
exit(0);
}
head=(STU*)malloc(len); //开辟内存
now=(STU*)malloc(len); //开辟内存
if(fread(now,len,1,fp)==NULL){
printf("Wrong.");
exit(0);
}
head->next=now;
p=now;
while(now->next!=NULL){
now=(STU*)malloc(len);
fread(now,len,1,fp);
p->next=now;
p=now;
}
return head;
}
void Output(STU* head) {//以指向链表头结点的指针为参数,将链表中所有学生的信息表格化输出
now = head->next;
while (now) {
printf("%s\t%8s\t%8s\t%d\t%d\t%d\t%d\t\n",now->num,now->name,now->major,now->classNo,now->score[0],now->score[1],now->score[2]);
now = now->next;
}
}
void Outprintf(STU* head) {//以指向链表头结点的指针为参数,将链表中所有学生的信息表格化输出(无头)
now = head;
while (now) {
printf("%s\t%8s\t%8s\t%d\t%d\t%d\t%d\t\n",now->num,now->name,now->major,now->classNo,now->score[0],now->score[1],now->score[2]);
now = now->next;
}
}
STU* Search_num(STU* head, char* num) {//查找指定学号的学生,返回指向该学生结点的指针
now = head->next;
while (now != NULL && strcmp(now->num,num)!=0) {
now = now->next;
}
return now;
}
STU* Input(){//输入学生信息
int n = 0;
printf("请录入这12名学生的信息:\n");
STU* p1, * p2;
head = (STU*)malloc(len);
while (n < 12){
p1 = (STU*)malloc(len);
scanf("%s%s%s%d%d%d%d", &p1->num, &p1->name, &p1->major, &p1->classNo, &p1->score[0], &p1->score[1], &p1->score[2]);
n++;
if (n == 1)
head->next = p1;
else
p2->next = p1;
p2 = p1;
}
p2->next = NULL;
return(head);
}
void Save(STU *head){//保存数据文件
p=head->next;
FILE *fp;
char filename[15];
getchar();
printf("请输入要建立的文件的名称:\n");
scanf("%s",&filename);
if((fp=fopen(filename,"wb"))==NULL){
printf("Wrong.");
exit(0);
}
while(p!=NULL){
if(fwrite(p,len,1,fp)!=1){
printf("Wrong.\n");
}
p=p->next;
}
printf("文件保存完成!\n\n");
fclose(fp);
}
void Store(STU *head){//保存无头数据文件
p=head;
FILE *fp;
char filename[15];
getchar();
printf("请输入要建立的文件的名称:\n");
scanf("%s",&filename);
if((fp=fopen(filename,"wb"))==NULL){
printf("Wrong.");
exit(0);
}
while(p!=NULL){
if(fwrite(p,len,1,fp)!=1){
printf("Wrong.\n");
}
p=p->next;
}
printf("文件保存完成!\n\n");
fclose(fp);
}
void OutOneNode(STU *p){//输出参数所指的链表中一个结点的指针
printf("%s\t%8s\t%8s\t%d\t%d\t%d\t%d\t\n",p->num,p->name,p->major,p->classNo,p->score[0],p->score[1],p->score[2]);
}
5.程序运行截图
更多推荐
所有评论(0)