实验内容
[问题描述]
学生信息管理系统
[基本要求]
设计一个学生信息管理系统,学生对象至少要包含:学号、姓名、性别、成绩1、成绩2、总成绩等信息。要求实现以下功能:
1.试选择一种方式存储:基于数组、链表或文件方式
2.总成绩要求自动计算;
3.查询:分别给定学生学号、姓名,能够查找到学生的基本信息(要求至少用两种查找算法实现);
排序:分别按学生的学号、总成绩进行排序(要求至少用两种排序算法实现)。
[测试数据]
由学生依据软件工程的测试技术自己确定。
主要思想
建立结构体,从文件中读入数据到结构体中。设立两个函数,功能分别为输出菜单和全部信息,以备重复调用。对学号使用冒泡排序,即依次比较相邻的两个数,将小数放在前面,大数放在后面,对总成绩使用堆排序,先建初堆,再调整堆,最后进行堆排序。按姓名查找时使用顺序查找,按学号查找时使用折半查找,需要注意的是,折半查找学号要保证学号是有序的。
代码实现
#include<stdio.h>//实验五
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
typedef struct{
char num[4];
char name[10];
char sex[4];
int score1;
int score2;
int sum;
}StuType;//学生信息结构体
typedef struct{
StuType S[15];
int stunum;
}Student;//学生信息表
void menu(){//菜单
cout<<"***************学生信息管理系统***************"<<endl;
cout<<" 1、根据学号查找学生"<<endl;
cout<<" 2、根据姓名查找学生"<<endl;
cout<<" 3、根据学号排序输出"<<endl;
cout<<" 4、根据总成绩排序输出"<<endl;
cout<<" 5、退出"<<endl;
cout<<"**********************************************"<<endl;
cout<<"请选择...\n";
}
void Allprint(Student &Stu){//打印全部信息
printf("学号\t姓名\t性别\t成绩1\t成绩2\t总成绩\n");
for (int i =1;i<=Stu.stunum;i++)
{
printf("%s\t%s\t%s\t%d\t%d\t%d\n",Stu.S[i].num,Stu.S[i].name,Stu.S[i].sex,Stu.S[i].score1,
Stu.S[i].score2,Stu.S[i].sum);
}
}
void Read(Student &Stu){//从文件中读入信息到结构体
FILE *fp=fopen("C:\\Users\\chenxianning\\Documents\\c c++\\数据结构课设\\students.txt","rb");
if(fp==NULL){//判断文件是否可以打开
cout<<"can not open the file"<<endl;
exit(0);
}
for(int i=1;;i++){
int n=fscanf(fp,"%s%s%s%d%d",Stu.S[i].num,Stu.S[i].name,Stu.S[i].sex,&Stu.S[i].score1,&Stu.S[i].score2);
Stu.S[i].sum=Stu.S[i].score1+Stu.S[i].score2;//计算总成绩
if(n==-1){//文件读入结束
Stu.stunum=i-1;
fclose(fp);
break;
}
}
fclose(fp);//关闭文件
}
void NumSort(Student &Stu){ //冒泡排序
int m=Stu.stunum;
int flag=1;//标记某一趟排序是否发生交换
int j;
StuType t;
while((m>0)&&(flag==1)){//flag置为0,如果本次没有发生交换,就不会执行下一趟
flag=0;
for(j=1;j<m;j++)
if(strcmp(Stu.S[j].num,Stu.S[j+1].num)>0)
{
flag=1;
t=Stu.S[j];//交换前后记录
Stu.S[j]=Stu.S[j+1];
Stu.S[j+1]=t;
}
--m;
}
}
void HeapAdjust(Student &Stu,int s,int m){//调整堆
StuType rc=Stu.S[s];
for(int j=2*s;j<=m;j*=2){//沿key值较大的孩子结点向下筛选
if(j<m&&Stu.S[j].sum<Stu.S[j+1].sum)++j;//j为key值较大的记录的下标
if(rc.sum>=Stu.S[j].sum)break;//rc应插在位置s上
Stu.S[s]=Stu.S[j];
s=j;
}
Stu.S[s]=rc;//插入
}
void CreatHeap(Student &Stu){//建初堆
int n=Stu.stunum;//建成大根堆
for(int i=n/2;i>0;--i)
HeapAdjust(Stu,i,n);
}
void SumSort(Student &Stu){//堆排序
CreatHeap(Stu);
StuType t;
for(int i=Stu.stunum;i>1;--i){
t=Stu.S[1];//把堆顶元素和未经排序子序列中最后一个元素做交换
Stu.S[1]=Stu.S[i];
Stu.S[i]=t;
HeapAdjust(Stu,1,i-1);
}
Allprint(Stu);
}
void NameSearch(Student &Stu){//顺序查找
cout<<"请输入该学生的姓名:";
char key[4];
cin>>key;
int nn,i;
strcpy(Stu.S[0].name,key);//哨兵
for(i=Stu.stunum;;--i)//从后往前找
if(strcmp(Stu.S[i].name,Stu.S[0].name)==0)
{
nn=i;
break;
}
nn=i;
if(i==0)
{
cout<<"查无此人!"<<endl;
return;
}
cout<<"查询成功!"<<endl;
cout<<"学号:"<<Stu.S[nn].num<<" 姓名:"<<Stu.S[nn].name<<" 性别:"<<Stu.S[nn].sex<<" 成绩1:"<<Stu.S[nn].score1
<<" 成绩2:"<<Stu.S[nn].score2<<" 总成绩:"<<Stu.S[nn].sum<<endl;
}
void NumSearch(Student &Stu){//折半查找
NumSort(Stu);
cout<<"请输入该学生的学号:";
char key[4];
cin>>key;
int nn=0;
int low,high,mid;
low=1;//置查找区间初值
high=Stu.stunum;
while(low<=high)
{
mid=(high+low)/2;
if(strcmp(key,Stu.S[mid].num)==0)//找到待查元素
{
nn=mid;
break;
}
else if(strcmp(key,Stu.S[mid].num)<0)//继续在前一子表进行查找
high=mid-1;
else//继续在后一子表进行查找
low=mid+1;
}
cout<<"查询成功!"<<endl;
cout<<"学号:"<<Stu.S[nn].num<<" 姓名:"<<Stu.S[nn].name<<" 性别:"<<Stu.S[nn].sex<<" 成绩1:"<<Stu.S[nn].score1
<<" 成绩2:"<<Stu.S[nn].score2<<" 总成绩:"<<Stu.S[nn].sum<<endl;
return;
}
int main(){
Student Stu;
Read(Stu);
int m;
while(m!=5){
menu();
cin>>m;
switch(m){
case 1:
NumSearch(Stu);
break;
case 2:
NameSearch(Stu);
break;
case 3:
NumSort(Stu);
Allprint(Stu);
break;
case 4:
SumSort(Stu);
break;
case 5:
cout<<"感谢您的使用!"<<endl;
return 0;
default:
cout<<"没有该选项!"<<endl;
break;
}
system("pause");
system("cls");
}
return 0;
}