#include<iostream>
#include<string>
#include<fstream>
using namespace std;
struct score //定义存放学生信息的结点
{
int num; //学号
string name; //姓名
string major; //专业
string classes; //班级
string sex; //性别
int age; //年龄
struct score* next; //next为指向下一结点的指针
};
struct score* head; //指向链表头结点的指针
struct score* head2; //指向链表头结点的指针
struct score* head3; //指向链表头结点的指针
int studentSum = 0; //学生总人数
class record
{
public:
struct score* InsertRecord(struct score* h);//插入学生信息
struct score* DeleteRecord(struct score* h);//删除学生信息
struct score* AUpdateRecord(struct score* h, int x);//修改学生信息
void FindRecord(struct score* h, string x); //根据学生姓名查询学生信息
void FindRecord(struct score* h, int x); //根据学生学号查询学生信息
void MajorRecordFind(struct score* h, string x); //统计指定专业的学生人数,并显示全部指定专业学生信息
void ClasRecordFind(struct score* h, string x); //统计指定班级的学生人数,并显示全部指定班级学生信息
void AgeRecordFind(struct score* h, int x); //统计指定年龄的学生人数,并显示全部指定年龄学生信息
void SexRecordFind(struct score* h, string x); //统计指定性别的学生人数,并显示全部指定性别学生信息
void PrintRecord(struct score* h); //输出所有学生信息
void SaveRecordFile(struct score* h); //保存学生信息到文件
struct score* LoadRecordFile(struct score* h); //从文件中加载学生信息
};
score* Merge_List(score* list1, score* list2) {
if (list1 == nullptr)
return list2;
if (list2 == nullptr)
return list1;
if (list1->num < list2->num)
{
list1->next = Merge_List(list1->next, list2);
return list1;
}
else
{
list2->next = Merge_List(list1, list2->next);
return list2;
}
return list1->num <= list2->num ? list1 : list2;
}
struct score* record::InsertRecord(struct score* h)
{
struct score* p1, * p2, * p3;
p3 = new score; //创建新的学生结点
cout << "\n请输入学生学号:";
cin >> p3->num;
cout << "\n请输入学生姓名:";
cin >> p3->name;
cout << "\n请输入学生的专业:";
cin >> p3->major;
cout << "\n请输入学生的班级:";
cin >> p3->classes;
cout << "\n请输入学生的性别:";
cin >> p3->sex;
cout << "\n请输入学生的年龄:";
cin >> p3->age;
p3->next = NULL; //将要插入结点的指针域置为空
if (h == NULL)
{
h = p3;
return h;
}
p1 = p2 = h;
while (p1 != NULL && p3->num > p1->num) //查找结点的学号大于要插入结点的学号的第一个结点
{ //指针p1表示符合条件的结点的指针,指针p2是指针p1的前一个结点的指针
p2 = p1;
p1 = p1->next;
}
if (p1 == h) //插入位置为链表头结点前
{
p3->next = h;
h = p3;
return h;
}
else //插入位置为链表的中间的链表的尾部
{
p2->next = p3;
p3->next = p1;
}
studentSum += 1; //学生人数加1
return h; //返回链表的头结点
}
void record::PrintRecord(score* h)
{
if (h == NULL)
{
cout << "\n抱歉,没有任何记录!";
return;
}
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
while (h) //输出链表中每个结点的学生信息
{
cout << h->num << "\t" << h->name << "\t" << h->major << "\t" << h->classes << "\t" << h->sex << "\t" << h->age << endl;
h = h->next;
}
}
struct score* record::DeleteRecord(struct score* h)
{
struct score* p1, * p2;
int num;
if (h == NULL) //链表为空
{
cout << "\n抱歉,没有任何记录!";
return h;
}
p1 = p2 = h;//将链表的头指针赋给指针p1和p2
cout << "\n请输入要删除记录的学生学号:";
cin >> num;
while (p1 != NULL && p1->num != num)//查找结点的学号等于要删除学生学号的第一个结点
{ //指针p1表示符合条件的结点的指针,指针p2是指针p1的前一个结点指针
p2 = p1;
p1 = p1->next;
}
if (p1 == NULL)
{
cout << "\n抱歉啊,表中没有该记录哦!";
return h;
}
if (p1->num == num)
{
studentSum -= 1;//学生人数减1
if (p1 == h) //删除的是头结点
h = h->next;
else //删除的是非头结点
p2->next = p1->next;
delete p1; //释放p1所指向的存储单元
}
return h;
}
struct score* record::AUpdateRecord(struct score* h,int x)//修改学生信息
{
struct score* p1;
int num;
if (h == NULL)
{
cout << "\n抱歉,没有任何记录!";
return h;
}
p1 = h;
cout << "\n请输入要修改记录的学生学号:";
cin >> num;
while (p1 != NULL && p1->num != num) //查找结点的学号等于要修改学生学号的结点指针
{
p1 = p1->next; //将p1指针移到下一个结点
}
if (p1 == NULL) //没有找到符合要求的结点
{
cout << "\n抱歉,表中没有该记录!";
return h;
}
if (p1->num == num) //找到符合要求的结点,并修改学生的相关信息
{
if (x == 1)
{
cout << "\n请重新输入学生的姓名:";
cin >> p1->name;
}
if (x == 2)
{
cout << "\n请重新输入学生的专业:";
cin >> p1->major;
}
else if (x == 3)
{
cout << "\n请重新输入学生的班级:";
cin >> p1->classes;
}
else if (x == 4)
{
cout << "\n请重新输入学生的性别:";
cin >> p1->sex;
}
else if (x == 5)
{
cout << "\n请重新输入学生的年龄:";
cin >> p1->age;
}
}
return h;
}
void record::FindRecord(struct score* h, int num) //根据学生学号查找学生信息
{
struct score* p1;
if (h == NULL)
{
cout << "\n抱歉,没有任何记录";
return;
}
p1 = h; //将链表的头结点指针h赋给指针p1
while (p1 != NULL && p1->num != num) //查找结点的学号等于要查找学生学号的结点指针
{
p1 = p1->next;
}
if (p1 == NULL) //没有找到
{
cout << "抱歉啊,表中没有该记录的哦!";
return;
}
if (p1->num == num) //找到并显示信息
{
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
cout << p1->num << "\t" << p1->name << "\t" << p1->major << "\t" << p1->classes << "\t" << p1->sex << "\t" << p1->age << endl;
}
}
void record::FindRecord(struct score* h, string name) //根据学生姓名查找学生信息
{
struct score* p1;
if (h == NULL)
{
cout << "\n抱歉,没有任何记录!";
return;
}
p1 = h;
while (p1 != NULL && p1->name != name) //查找结点的姓名等于要查找学生姓名的结点指针
{
p1 = p1->next;
}
if (p1 == NULL)
{
cout << "\n抱歉,表中没有该记录!";
return;
}
if (p1->name == name)
{
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
cout << p1->num << "\t" << p1->name << "\t" << p1->major << "\t" << p1->classes << "\t" << p1->sex << "\t" << p1->age << endl;
}
}
void record::MajorRecordFind(struct score* h, string major)//按专业查询
{
struct score* p = h;
int count = 0;
if (p == NULL)
{
cout << "\n抱歉,没有任何记录!";
return;
}
while (p)
{
if (p->major == major) //查找结点的专业等于要查找学生专业的结点指针
{
count += 1;
}
p = p->next;
}
cout << "该专业的人数为:";
cout << count << endl;
cout << "改专业的学生信息为:" << endl;
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
p = h;
while (p)
{
if (p->major == major)
cout << p->num << "\t" << p->name << "\t" << p->major << "\t" << p->classes << "\t" << p->sex << "\t" << p->age << endl;
p = p->next;
}
}
void record::ClasRecordFind(struct score* h, string classes)//按班级查询
{
struct score* p = h;
int count = 0;
if (p == NULL)
{
cout << "\n抱歉,没有任何记录!";
return;
}
while (p)
{
if (p->classes == classes) //查找结点的班级等于要查找学生班级的结点指针
{
count += 1;
}
p = p->next;
}
cout << "该班级的人数为:";
cout << count << endl;
cout << "该班级的学生信息为:" << endl;
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
p = h;
while (p)
{
if (p->classes == classes)
cout << p->num << "\t" << p->name << "\t" << p->major << "\t" << p->classes << "\t" << p->sex << "\t" << p->age << endl;
p = p->next;
}
}
void record::SexRecordFind(struct score* h,string sex)//按性别查询
{
struct score* p = h;
int count = 0;
if (p == NULL)
{
cout << "\n抱歉,没有任何记录!";
return;
}
while (p)
{
if ( p->sex == sex) //查找结点的性别等于要查找学生性别的结点指针
{
count += 1;
}
p = p->next;
}
cout << "该性别的人数为:";
cout << count << endl;
cout << "该性别的学生信息为:" << endl;
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
p = h;
while (p)
{
if (p->sex == sex)
cout << p->num << "\t" << p->name << "\t" << p->major << "\t" << p->classes << "\t" << p->sex << "\t" << p->age << endl;
p = p->next;
}
}
void record::AgeRecordFind(struct score* h, int age)//按年龄查询
{
struct score* p = h;
int count = 0;
if (p == NULL)
{
cout << "\n抱歉,没有任何记录!";
return;
}
while (p)
{
if (p->age == age) //查找结点的年龄等于要查找学生年龄的结点指针
{
count += 1;
}
p = p->next;
}
cout << "该年龄的人数为:";
cout << count << endl;
cout << "改年龄的学生信息为:" << endl;
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
p = h;
while (p)
{
if (p->age == age)
cout << p->num << "\t" << p->name << "\t" << p->major << "\t" << p->classes << "\t" << p->sex << "\t" << p->age << endl;
p = p->next;
}
}
void record::SaveRecordFile(struct score* h) //将链表中的数据写入文件
{
struct score* p;
ofstream ofile; //定义输出文件对象
ofile.open("score.dat", ios::out); //以定的方式打开文件score.dat,若该文件不存在,则创建score.dat文件
if (!ofile)
{
cout << "\n数据文件打开错误没有将数据写入文件!\n";
return;
}
cout << "\n学号 \t姓名 \t专业\t班级\t性别\t年龄" << endl;
while (h)
{
ofile << endl << h->num << "\t" << h->name << "\t" << "\t" << h->major << "\t" << h->classes << "\t" << h->sex << "\t" << h->age;
p = h; //将当前结点的数据信息写入到文件中
h = h->next;
delete p;
}
ofile.close();
}
struct score* record::LoadRecordFile(struct score* h)
{
ifstream ifile; //定义输入文件对象
ifile.open("score.dat", ios::in);//以读写方式打开文件score.dat
struct score* p;
struct score* q = nullptr;
if (!ifile)
{
cout << "\n数据文件不存在,加载不成功!\n";
return NULL;
}
char s[50];
ifile.getline(s, 50); //读取文件指针当前行数据
while (!ifile.eof())
{
studentSum = studentSum + 1;
p = new score;
ifile >> p->num >> p->name >> p->major >> p->classes >> p->sex >> p->age; //
p->next = NULL;
if (h == NULL)
{
q = h = p;
}
else
{
q ->next = p;
q = p;
}
}
ifile.close();
return h;
}
void SystemMenu(record r)
{
int choice;
while (1)
{
cout << "\n\t\t欢迎进入学生信息管理系统!";
cout << "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
cout << "\n\t1、添加学生信息";
cout << "\n\t2、删除学生信息";
cout << "\n\t3、修改学生信息";
cout << "\n\t4、查询学生信息";
cout << "\n\t5、显示所有学生信息";
cout << "\n\t6、合并链表";
cout << "\n\t0、退出系统";
cout << "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
cout << "\n请根据提示选择操作:";
cin >> choice;
switch (choice)
{
case 1: //增加学生信息
while (1)
{
int c;
cout << "\n*************************************";
cout << "\n\t1、添加到主表(可存储)";
cout << "\n\t2、添加到副表(临时表不可存储)";
cout << "\n\t3、返回上级目录";
cout << "\n*************************************";
cout << "\n请根据提示选择操作:"; //显示查询子菜单
cin >> c;
if (c ==1)
{
head = r.InsertRecord(head);
}
if (c == 2)
{
head2 = r.InsertRecord(head2);
}
if (c == 3) //退出查询子菜单
break;
}
break;
case 2: //删除学生信息
head = r.DeleteRecord(head);
break;
case 3: //修改学生信息
while (1)
{
int c;
cout << "\n*************************************";
cout << "\n\t1、修改一项,姓名";
cout << "\n\t2、修改一项,专业";
cout << "\n\t3、修改一项,班级";
cout << "\n\t4、修改一项,性别";
cout << "\n\t5、修改一项,年龄";
cout << "\n\t6、返回上级目录";
cout << "\n*************************************";
cout << "\n请根据提示选择操作:"; //显示查询子菜单
cin >> c;
if (c==1||c==2||c==3||c==4||c==5) //修改一项
{
head = r.AUpdateRecord(head,c);
}
if (c == 6) //退出查询子菜单
break;
}
break;
case 4: //查询学生信息
while (1)
{
int c;
cout << "\n*************************************";
cout << "\n\t1、根据学号查询学生信息";
cout << "\n\t2、根据姓名查询学生信息";
cout << "\n\t3、根据专业查询学生信息";
cout << "\n\t4、根据班级查询学生信息";
cout << "\n\t5、根据性别查询学生信息";
cout << "\n\t6、根据年龄查询学生信息";
cout << "\n\t7、返回上级目录";
cout << "\n*************************************";
cout << "\n请根据提示选择操作:"; //显示查询子菜单
cin >> c;
if (c == 1) //根据学生学号查询学生信息
{
int x;
cout << "\n请输入需要查询的学生学号:";
cin >> x;
r.FindRecord(head, x);
}
if (c == 2) //根据学生姓名查询学生信息
{
string name;
cout << "\n请输入需要查询的学生姓名:";
cin >> name;
r.FindRecord(head, name);
}
if (c == 3) //根据专业查询学生信息
{
string major;
cout << "\n请输入需要查询的学生专业:";
cin >> major;
r.MajorRecordFind(head, major);
}
if (c == 4) //根据班级查询学生信息
{
string classes;
cout << "\n请输入需要查询的学生班级:";
cin >> classes;
r.ClasRecordFind(head, classes);
}
if (c == 5) //根据性别查询学生信息
{
string sex;
cout << "\n请输入需要查询的学生性别:";
cin >> sex;
r.SexRecordFind (head, sex);
}
if (c == 6) //根据年龄查询学生信息
{
int age;
cout << "\n请输入需要查询的学生年龄:";
cin >> age;
r.AgeRecordFind(head, age);
}
if (c == 7) //退出查询子菜单
break;
}
break;
case 5: //输出所有学生成绩信息
while (1)
{
int c;
cout << "\n*************************************";
cout << "\n\t1、输出主表学生信息";
cout << "\n\t2、输出副表学生信息";
cout << "\n\t3、返回上级目录";
cout << "\n*************************************";
cout << "\n请根据提示选择操作:"; //显示查询子菜单
cin >> c;
if (c == 1 )
{
r.PrintRecord(head);
}
if (c == 2)
{
r.PrintRecord(head2);
}
if (c ==3) //退出查询子菜单
break;
}
break;
case 6: //
head3 = Merge_List(head, head2);//合并a,b
break;
}
if (choice == 0)//退出系统
break;
}
}
int main()
{
head = NULL;
record r; //定义record类的对象r
head = r.LoadRecordFile(head); //将文件中的数据读取到链表中
SystemMenu(r); //显示系统菜单,并处理用户选择
r.SaveRecordFile(head); //将链表中的数据写到文件中
return 0;
}
任务
采用链式存储完成学生信息的管理。学生信息包括:学号、姓名、专业、班级、性别、年龄等。要求实现学生信息数据的录入、插入、删除、查找、修改、排序、合并等。具体步骤包括:定义链表(任一种)的存储结构、实现相应基本操作、实现学生信息数据的管理;对链表中的学生信息按学号从小到大排序;将两个存储了学生信息的有序链表合并成一个链表。
说明
1、定义学生结构体Student,
成员有:
学号(num【int】),姓名(name【string】),
专业(major【string】),班级(grade【string】),
性别(sex【string】),年龄(age【int】)。
定义链式存储结构体:
struct score* next; //next为指向下一结点的指针,struct score* head; //指向链表头结点的指针,struct score* head2; //指向链表头结点的指针,struct score* head3; //指向链表头结点的指针
2、由于涉及到的函数比较多,这里只对重点函数进行设计说明;
1)插入函数:先判断链表内是否有数据,如果没有,直接将头指针指向此数据,如果有数据,先进行比较大小,在合适的位置上插入数据。
2)删除函数:用P2保存要删除的元素的前一个元素,将p2的后继直接指向要删除元素的下一个元素。
3)合并两个链表,在系统中存在主表和副表,主表数据可以保存,副表不可以,合并链表时采用归并递归,将所有数据存储到主表内。