学生信息管理系统C++

设计目的

  1. 使学生进一步理解和掌握课堂上所学的面向对象C++编程知识,巩固和加深学生对C++面向对象课程的基本知识的理解和掌握。
  2. 掌握C++面向对象编程和程序调试的基本技能,学会利用C++语言进行基本的软件设计,着重提高运用C++面向对象语言解决实际问题的能力。
  3. 掌握书写程序设计说明文档的能力,使学生学会使用各种计算机资料和查阅有关参考资料解决问题的方法。

具体要求

运用C++语言描述学生类,每一个类应包含数据成员和成员函数。学生的信息包括学号、姓名、性别、班级、高数成绩和英语成绩。注重面向对象程序设计理论知识的理解与实际的动手编程能力,要求学生设计具有继承与派生以及多态性的类,理解面向对象程序设计的核心的概念。

本题目要实现的主要功能如下:

  1. 建立基类—学生类,数据成员包括学号、姓名、性别;
  2. 派生类—电信类,新增数据成员有:班级、高数成绩、英语成绩;
  3. 能够实现对电信类学生信息的录入、修改、查找、排序、删除等功能;
  4. 能够输出总成绩,即高数和英语两门课的成绩之和;
  5. 能够对学生信息按高数成绩从高到低进行排序,若高数成绩一样,则按英语成绩排序,若成绩都一样,则按学号进行排序;
  6. 查找功能支持姓名查找或学号查找
  7. 若通过动态分配内存的链表或哈希表实现

设计思路

首先数据都是放在类中的,在创建一个结构体进行类与链表的结合使用完成学生信息管理系统。

分别在类与链表结构体中封装对象指针,方便之后形成链表结点对其进行控制。每个功能函数都被封装在链表结构体中,因为需要使用内部的指针,这样比较方便。

我采用的是带头双向链表来实现,这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。链表为空时,也会有一个哨兵位的头结点(head),这样我们每次去实现功能的时候,不需要遍历。直接让当前结点指向头结点就可以从头开始依次下去,这也是我比较喜欢的一点。

主函数(main)中是实现这些功能的,但需要先创建一个头结点(空的),然后录入的时候进行结点之间的链接即可。
通过程序主界面写一个菜单,然后通过分支函数switch进行选择。

我认为类和链表的最大难点只需要想通它们之间的指针关系即可,只要理解了指针指向,就可以通过指针实现所有功能。

1. 录入信息

通过for循环可以控制输入的人数,这样想要插入多个学生数据时不用每次都调用Input()函数;在for循环中每次插入数据之前要记得开辟空间,更新指针的指向,录入信息是以后所有功能的基础,如果这步出错,接下来的所有功能实现都会有问题,特别是打印,录入成功但是什么都没打印出来。所以需要尤为注意!
我这里使用的是头插,所以每次扩容之后,都会present->pre=NULL;
插入信息之后,此时就顺势将英语成绩与高数成绩相加算出总分,之后打印直接打印总分会方便很多。
每次输入都会new一个新的类出来,不插入就不用开辟空间,之前也没有定了空间大小,我觉得这也是一种动态开辟的方法,而且简单易懂还很方便。

2.浏览信息

浏览所有信息,就是将所有信息打印出来。因为格式与录入的不一样,我使用了setw函数可以让表格对齐观感更好(注意使用要包头文件iomanip)。将表头信息封装成了display函数,在以后需要打印的时候直接调用,代码会更加整洁。因为链表中不是只有一组数据(一个结点),所以想要打印全部的数据需要使用while循环,然后更新指针指向即可。

3.查找信息

可以通过学生姓名与学生学号进行查找,只需要从头开始present=head;然后当想要查找的姓名或学号等于present-》Name与present->num即可
我将查找的函数封装成了bool类型的(其余都是void),方便接下来的删除和修改模块。因为想要删除和修改也需要在链表中找到相关的数据才可以进行相关操作,需要的时候直接调用就行,很方便。
因为通过姓名和学号是两种不同的方式(但是底层实现都一样),所以我又另外写了一个选择查找通过switch进行不同的选择。

4.删除信息

这个功能模块,说实话不是很难,但是我卡了一天,原因是我的录入模块一开始没有写好,导致它只能删除最后插入的数据,也就是头结点。浪费了我很多时间。所以说录入是基础!!!
当删除的是头结点和不是头结点的有两种处理方式

5.修改信息

通过Check函数查找想要修改的学生学号,找到重新输入即可。

6.排序

通过简单的冒泡排序实现。当当前结点比下一个结点大就交换。
因为按实训要求,需要对学生信息按高数成绩从高到低进行排序,若高数成绩一样,则按英语成绩排序,若成绩都一样,则按学号进行排序。所以直接嵌套就行。
之前我觉得代码太过凌乱了,想着封装成三个函数,然后达到条件之后依次调用,但是真正实现的时候,可以排序成功,但是一旦进入在排序中调用另一个函数,代码就不接着往下跑了,终止main函数中的循环了。我觉得是因为代码嵌套程度太高程序奔溃了,所以我就按一个函数的方式写了。虽然看着有些复杂,但是不会出错。

完整代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
#include <iomanip>using namespace std;class Student
{
public:int num;string name;string sex;};//电信类中存放学生数据
class DX :public Student
{
public:int classroom;int hmath;int eng;int sum;//总分DX *next;//电信类指针,指向下一结点DX* pre;//指向前一个结点};//双向链表
struct Linklist
{DX* head;//头指针DX *present;//当前指针void Input();//录入void Creat();//扩容bool Check();//查找学号bool Check1();//查找姓名void SelectCheck();//选择查找 	void Output();//浏览void Delete();//删除void Modify();//修改void Sort();//排序,高数,英语,学号
}X;//开辟新空间,new一个类出来
void Linklist::Creat()
{//头插present = new DX;//当前指针为新开辟的这个电信类head = present;present->next = NULL;present->pre = NULL;//此时只有一个结点 
}void Linklist::Input()
{int size;//想要输入的学生个数cout << "请输入学生的人数:";cin >> size;//有几个人循环几次 for (int i = 0; i < size; i++){//在插入的时候就进行链表的链接 present = new DX;head->pre = present;present->next = head;head = present;//相当于头插present->pre = NULL;cout << "请输入第" << i + 1 << "个学生的学号:";cin >> present->num;cout << "请输入第" << i + 1 << "个学生的姓名:";cin >> present->name;cout << "请输入第" << i + 1 << "个学生的性别:";cin >> present->sex;cout << "请输入第" << i + 1 << "个学生的班级:";cin >> present->classroom;cout << "请输入第" << i + 1 << "个学生的高数成绩:";cin >> present->hmath;cout << "请输入第" << i + 1 << "个学生的英语成绩:";cin >> present->eng;present->sum = present->hmath + present->eng;cout << "-----------------------------" << endl;}cout << "录入成功!!!!" << endl;
}//打印表头信息
void display()
{cout << setw(30) << "学生成绩信息" << endl;  // setw函数设置字段宽度,需要引用头文件iomanip cout << " --------------------------------------------------------------------------" << endl;cout << setw(6) << "学号" << setw(12) << "姓名" << setw(8) << "性别" << setw(8)<< "班级" << setw(8) << "高数" << setw(8) << "英语" << setw(12) << "总分" << endl;cout << " --------------------------------------------------------------------------" << endl;
}void Linklist::Output()
{//从头开始 present = head;display();//打印出所有信息,直到末尾while (present->next != NULL){//setw函数是用来设置行间距的cout << setw(6) << present->num << setw(12) << present->name << setw(8) << present->sex<< setw(8) << present->classroom << setw(8) << present->hmath << setw(8) << present->eng<< setw(12) << present->sum << endl;cout << " --------------------------------------------------------------------------" << endl;present = present->next;//更新}}//精确查找
//要想用学生姓名查找将num改为name即可  int变为string 类型要匹配
bool Linklist::Check()
{present = head;int id;cin >> id;display();while (present->next != NULL){if (id == present->num){//找到打印出信息cout << setw(6) << present->num << setw(12) << present->name << setw(8) << present->sex<< setw(8) << present->classroom << setw(8) << present->hmath << setw(8) << present->eng<< setw(12) << present->sum << endl;cout << " --------------------------------------------------------------------------" << endl;return true;}else{//不同就接着找present = present->next;}}cout << "查无此人!!!!" << endl;return false;
}bool Linklist::Check1()
{present = head;//cout << "请输入需要查找的学生学号:";string nam;cin >> nam;display();while (present->next != NULL){if (nam == present->name){//找到打印出信息cout << setw(6) << present->num << setw(12) << present->name << setw(8) << present->sex<< setw(8) << present->classroom << setw(8) << present->hmath << setw(8) << present->eng<< setw(12) << present->sum << endl;cout << " --------------------------------------------------------------------------" << endl;return true;}else{//不同就接着找present = present->next;}}cout << "查无此人!!!!" << endl;return false;
}//选择查找
void Linklist::SelectCheck()
{cout << "1.按学号查询" << endl;cout << "2.按姓名查询" << endl;//cout << "3.按姓名进行模糊查询" << endl;cout << "请选择:";int a;cin >> a;switch (a){case 1:cout << "请输入需要查找的学生学号:";Check();break;case 2:cout << "请输入需要查找的学生姓名:";Check1();break;/*case 3:cout << "请输入需要模糊查找的学生姓名:";*/default:cout << "选择错误" << endl;break;}
}void Linklist::Modify()
{cout << "请输入你须要修改的学生的学号:";//输入学号在check函数中输入即可,不用另外写了 //先查看需要修改的信息是否存在if (Check()){//找到,重新录入即可 cout << "请输入修改后学生的学号:";cin >> present->num;cout << "请输入修改后学生的姓名:";cin >> present->name;cout << "请输入修改后学生的性别:";cin >> present->sex;cout << "请输入修改后学生的班级:";cin >> present->classroom;cout << "请输入修改后学生的高数成绩:";cin >> present->hmath;cout << "请输入修改后学生的英语成绩:";cin >> present->eng;present->sum = present->hmath + present->eng;cout << "修改成功!!!" << endl;}//找不到Check函数会自动return false else cout << "修改失败!" << endl;
}void Linklist::Delete()
{//删除学生信息cout << "请输入要删除的学生学号: ";if (Check()){if (present->pre == NULL){//头指针与当前指针指向同一个,将头指针给下一个 head = present->next;delete present;}else if (present->pre != NULL){//改变指针指向,前一个越过present 指向后一个//不改变之前两个等号右边都是present present->pre->next = present->next;present->next->pre = present->pre;delete present;}cout << "删除数据成功!" << endl;}else cout << "删除失败!" << endl;
}void Linklist::Sort()
{int  a = 1, b = 1;  present = head;
start:while (present->next->next != NULL){a = b;//排序,小的放前面 //高数if (present->hmath == present->next->hmath){if (present->eng == present->next->eng){//学号if (present->num < present->next->num){//无需互换 present = present->next;}else if (present->num > present->next->num&&present->pre == NULL){b++;DX* p = present;DX* q = p->next;p->next = q->next;q->next = p;p->pre = q;q->next = p;q->pre = NULL;}//中间结点,尾结点不作考虑 else if (present->num > present->next->num && present->pre != NULL){if (present->next->next != NULL){b++;DX* p = present;DX* q = p->next;p->pre->next = q;q->pre = p->pre;p->next = q->next;q->next->pre = p;p->pre = q;q->next = p;}}}//英语else if (present->eng < present->next->eng){//无需互换 present = present->next;}else if (present->eng > present->next->eng&&present->pre == NULL){b++;DX* p = present;DX* q = p->next;p->next = q->next;q->next = p;p->pre = q;q->next = p;q->pre = NULL;}//中间结点,尾结点不作考虑 else if (present->eng > present->next->eng && present->pre != NULL){if (present->next->next != NULL){b++;DX* p = present;DX* q = p->next;p->pre->next = q;q->pre = p->pre;p->next = q->next;q->next->pre = p;p->pre = q;q->next = p;}}}else if (present->hmath < present->next->hmath){//无需互换 present = present->next;}//头结点           else if (present->hmath > present->next->hmath&&present->pre == NULL){b++;DX* p = present;DX* q = p->next;p->next = q->next;q->next = p;p->pre = q;q->next = p;q->pre = NULL;}//中间结点,尾结点不作考虑 else if (present->hmath > present->next->hmath && present->pre != NULL){if (present->next->next != NULL){b++;DX* p = present;DX* q = p->next;p->pre->next = q;q->pre = p->pre;p->next = q->next;q->next->pre = p;p->pre = q;q->next = p;}}while (a != b){//若一次完整循环下来没有顺序变化,退出while (present->pre != NULL) {present = present->pre;} goto start;}}//没有此次向前遍历,排序过后链表中只会留下最后一次插入的数据 while (present->pre != NULL) { present = present->pre; }head = present;//因为头结点不为空,修改完后可能会被改变,此处从新定位头结点//打印出排序好的链表 display();do{cout << setw(6) << present->num << setw(12) << present->name << setw(8) << present->sex<< setw(8) << present->classroom << setw(8) << present->hmath << setw(8) << present->eng<< setw(12) << present->sum << endl;cout << " --------------------------------------------------------------------------" << endl;present = present->next;//更新} while (present->next != NULL);
}//菜单 
void menu()
{cout << "-----------------------------------------------" << endl;cout << "学生信息管理系统" << endl;cout << "0.退出系统" << endl;cout << "1.录入信息" << endl;cout << "2.删除信息" << endl;cout << "3.修改信息" << endl;cout << "4.查找信息" << endl;cout << "5.浏览信息" << endl;cout << "6.排序" << endl;cout << "-----------------------------------------------" << endl;cout << "请输入(0-6):";
}int main()
{X.Creat();//没有while循环switch语句只走一遍就结束了 while (1){menu();int input;cin >> input;switch (input){case 0:break;case 1:X.Input();break;case 2:X.Delete();break;case 3:X.Modify();break;case 4:X.SelectCheck();break;case 5:X.Output();break;case 6:X.Sort();break;default:cout << "输入错误!!!" << endl;break;}//退出循环if (input == 0){break;//终止while }}return 0;}

结果展现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/21653.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go Modules 使用

文章参考https://blog.csdn.net/wohu1104/article/details/110505489 不使用Go Modules&#xff0c;所有的依赖包都是存放在 GOPATH /pkg下&#xff0c;没有版本控制。如果 package 没有做到完全的向前兼容&#xff0c;会导致多个项目无法运行(包版本需求不同)。 于是推出了g…

秋招突击——第四弹——Java的SSN框架快速入门——Spring(2)

文章目录 前言其他Spring加载properties 容器创建容器获取beanBeanFactory容器总结 注解注解开发对定义bean纯注解开发Bean管理Bean作用范围Bean生命周期 注解开发依赖注入第三方bean管理第三方bean管理第三方bean注入 注解开发总结 Spring整合整合mybatis整合Junit AOPAOP核心…

【C、C++编译工具】CLion工具介绍与安装

一、问题 最近突发奇想想学学最开始接触的语言C&#xff0c;之前大学的时候用的更多的工具还是VC&#xff0c;工作后慢慢接触了CLion&#xff0c;跟pycharm其实差不多&#xff0c;都是集成开发环境&#xff08;IDE&#xff09; 解释&#xff1a;什么是 IDE&#xff1f; 根据计…

2024年5月 | deepin 深度应用商店-应用更新记录

新增应用 序号应用名称deepin 系统版本应用分类应用类型1HitPaw Watermark Removerdeepin V23图形图像wine2PDF to DOCX转换器deepin V23网络应用linux3天工 AIdeepin V20.9效率办公linux4稻壳阅读deepin 20.9 deepin V23效率办公linux5讯飞星火deepin V20.9效率办公linux6文…

扩散模型的技术原理和应用价值

引言 一、扩散模型的基本概念 扩散模型(Diffusion Models)是一种基于概率论的生成模型&#xff0c;最初源自物理学中的扩散过程理论&#xff0c;比如墨水在水中的扩散过程。在机器学习领域&#xff0c;这一概念被创造性地应用于数据生成任务&#xff0c;特别是图像和声音的合成…

Proxmox Backup Server 命名空间使用

作者&#xff1a;田逸&#xff08;formyz&#xff09; Proxmox Backup Server&#xff08;一下统称PBS&#xff09;从2.2版本开始&#xff0c;新增了命名空间这样一个功能。这个功能大大便利了多Proxmox VE集群或者单节点备份&#xff0c;在以前PBS版本中&#xff0c;如果有多个…

HTML旋转照片盒子

效果图 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible" content…

世界的本质是旋转(9) 利用声波传输mFSK多音调频文本

在上一篇文章中 &#xff0c;主要介绍的是使用专用的业余无线电设备传输调相波形。 对于买不起SDR设备的学生来说&#xff0c;可以使用这篇文章介绍的思路&#xff0c;使用声卡的数据线传输IQ路的基带数据。线路输入的好处&#xff1a; 不经过空气的媒介&#xff0c;波形的本…

江苏省汽车及零部件产业协作配套对接会在苏州举行

5月28日&#xff0c;江苏省汽车及零部件产业协作配套对接会暨“百场万企”大中小企业融通对接活动在苏州举办。本次活动以“深化整零协作&#xff0c;促进大中小企业融通发展”为主题&#xff0c;由江苏省工业和信息化厅、中国中检所属中国汽车工程研究院股份有限公司&#xff…

分享7个手机上堪称神器却鲜为人知的小众宝藏软件

分享7个手机上堪称神器却鲜为人知的小众宝藏软件&#xff0c;保证大家用过就舍不得卸载~ 1.志愿大师 马上就是高考季了&#xff0c;高考完的同学如果不知道该如何选专业&#xff0c;可以用这个软件来分析各个大学和专业设置等信息。 志愿大师是一款专为高考后学生设计的高效辅…

Others - 网友都是些人才,哈哈哈哈

感谢万能的网友们&#xff01; 原本枯燥的知识&#xff0c;在网友生动形象的表达下&#xff0c;也能简单易懂&#xff0c;哈哈哈哈

Prometheus+Altermanager实现钉钉告警

PrometheusAltermanager实现钉钉告警 Prometheus和Altermanager的安装这里就不赘述了&#xff0c;我之前的文章有写到 不记得的小伙伴可以去看看Prometheus和Altermanager的安装使用 直接开始上操作 下载钉钉并打开&#xff0c;先创建一个接收告警信息的钉钉群 添加一个自定…

【Nacos_bugs】java.lang.IllegalStateException: Failed to load ApplicationContext

报错原因 找不到配置文件。 Bug 排查 如果使用 Nacos 管理配置文件&#xff0c;需要检查本地 bootstrap.yml 配置是否出现问题&#xff1a; 检查点&#xff1a; 检查 Nacos 服务的地址有没有配置错误&#xff0c;如上图 ①&#xff0c;格式严格为 IP:端口号" 检查 D…

Ant Design Vue Pro流程分析记录

一、基本介绍 Ant Design Vue Pro提供了一套完整的解决方案&#xff0c;包括路由、状态管理、UI组件库、HTTP请求封装等&#xff0c;方便开发者快速搭建和维护企业级应用。 二、官网地址 Ant Design Pro of Vue 三、下载及安装 推荐使用Yarn 四、文件分布及说明 dist&#xf…

常见Rabbitmq面试题及答案总结

1、 什么是 rabbitmq 釆用AMQP高级消息队列协议的一种消息队列技术撮大的特点就是消费并不需要 确保提供方存在,实现了服务之间的高度解耦 2、 为什么要使rabbitmq &#xff08;1&#xff09; 在分布式系统下具备异步&#xff0c;削峰&#xff0c;负载均衡等一系列高级功能&…

企业百度百科如何修改

百度百科是一个可以让我们快速的了解一个企业情况的地方&#xff0c;同时也让我们的企业展示了什么&#xff0c;还有哪些是可以做的。 注册与登录 首先&#xff0c;你需要注册一个百度账号&#xff0c;并通过邮箱或手机进行验证。登录后&#xff0c;可以开始创建或编辑百度百科…

Leetcode - 周赛400

目录 一&#xff0c;3168. 候诊室中的最少椅子数 二&#xff0c;3169. 无需开会的工作日 三&#xff0c;3170. 删除星号以后字典序最小的字符串 四&#xff0c;3171. 找到按位与最接近 K 的子数组 一&#xff0c;3168. 候诊室中的最少椅子数 本题是一道模拟题&#xff0c;直…

归并排序法

归并排序法是典型的分治算法应用&#xff0c;1946年由冯.诺伊曼发明。 算法思路&#xff1a;归并排序算法有两个基本操作&#xff0c;一是分&#xff0c;也就是把原数组划分成两个子数组的过程&#xff0c;另一个是治&#xff0c;它将两个有序数组合并成一个更大的有序数组。 …

基于小波区间相关的信号降噪方法(MATLAB 2021B)

在我们处理信号过程中最重要的任务就是找到信号隐藏的规律和信号的特征。常用的傅里叶分析法只能用于在时间域或者频率域上分析信号&#xff0c;而通常的数据会在时间域和频率域均有特征。而小波分析是继傅里叶分析之后的一大突破性创新&#xff0c;也是近年来在学术界非常热门…

扩散世界模型已训练出赶超人类的智能体?

论文标题&#xff1a; Diffusion for World Modeling:Visual Details Matter in Atari 论文作者&#xff1a; Eloi Alonso, Adam Jelley, Vincent Micheli, Anssi Kanervisto, Amos Storkey, Tim Pearce, Franois Fleuret 项目地址&#xff1a; https://github.com/eloial…