学生信息管理系统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.rhkb.cn/news/339679.html

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

相关文章

kali系统baopoWiFi密码

kali系统baopoWiFi密码,仅供学习 取决强大的密码字典,如果别人密码设置的足够安全,也无法破解成功,并不是100%破解 一、准备一个无线网卡&#xff0c;需要免驱动&#xff0c;最好知道频率2.4HGZ还是5.0GHZ 二、插上USB接口&#xff0c;vmware模拟器选择连接虚拟机 三、输入命…

超强算力 Orange Pi Kunpeng Pro 开发板基础测评与体验

目录 开箱体验资源简介系统启动连接网络登录系统通过桌面登录通过串口登录通过 SSH 登录配置散热风扇 算力测试MNIST示例MBNET示例 体验总结 大家好&#xff0c;我是 Hello 阿尔法&#xff0c;有幸接到 CSDN 的邀请参与 Orange Pi Kunpeng Pro 开发板的测评活动&#xff0c;本文…

基于数据驱动的自适应性小波构造(MATLAB)

以地震领域为例&#xff0c;时频变换能够刻画地震资料的时频特征&#xff0c;进而辅助地质构造解释。在各种时频分析工具中&#xff0c;连续小波变换CWT是描述地震资料时频特征的常用工具。选择合适的基小波是CWT的关键问题。对于不同类型的信号前人有针对性的设计了许多基小波…

基于单片机的超声波倒车雷达设计

摘 要&#xff1a;文 章设计了一种基于单片机的超声波倒车雷达系统&#xff0c;以 AT89C51 型单片机作为控制核心&#xff0c;集距离测量、显示&#xff0c;方位显示和危险报警于一体&#xff0c;以提高驾驶者在倒车泊车时的安全性和舒适性。本设计采用 Keil 软件对系统程序…

Linux开发工具(个人使用)

Linux开发工具 1.Linux yum软件包管理器1.1Linux安装程序有三种方式1.2注意事项1.3如何查看&#xff0c;安装&#xff0c;卸载软件包1.3.1查看软件包1.3.2安装软件包1.3.3卸载软件 2.Linux vim编辑器2.1vim的基本操作2.2vim正常模式命令集2.3vim底行模式命令集2.4vim配置 3.Lin…

就凭这张图,下订华为享界S9

文 | Auto芯球 作者 | 雷慢 冲啦&#xff01;就在刚刚&#xff0c; 我们团队下订了一辆享界S9&#xff0c; 还琢磨买奔驰S级&#xff0c;宝马7系和奥迪A8的老板们&#xff0c; 是应该试试享界S9了&#xff0c; 至少先占个坑&#xff0c;8月底S9上市当天&#xff0c; 可以…

微型导轨在自动化制造中有哪些优势?

微型导轨在自动化制造中发挥重要作用&#xff0c;能够满足自动化设备制造中对精度要求较高的工艺环节。适用于自动装配线、自动检测设备和机器人操作等环节&#xff0c;推动了行业的进步与发展。那么&#xff0c;微型导轨在使用中有哪些优势呢&#xff1f; 1、精度高和稳定性强…

FPGA DMA IP核使用指南

摘要 本文旨在介绍FPGA中DMA(Direct Memory Access)IP核的使用,包括其基本框架、测试代码编写以及仿真波形的分析。DMA是一种允许外围设备直接与内存进行数据交换的技术,无需CPU的介入,从而提高了数据传输的效率。 1. 引言 在现代FPGA设计中,DMA IP核因其…

android睡眠分期图

一、效果图 做医疗类项目&#xff0c;经常会遇到做各种图表&#xff0c;本文做的睡眠分期图。 二、代码 引入用到的库 api joda-time:joda-time:2.10.1 调用代码 /*** 睡眠* 分期*/private SleepChartAdapter mAdapter;private SleepChartAttrs mAttrs;private List<SleepI…

C基础-标准库上

下:http://t.csdnimg.cn/LXa0J C 标准库是一组 C 内置函数、常量和头文件&#xff0c;比如 <stdio.h>、<stdlib.h>、<math.h>&#xff0c;等等。 目录 一. assert.h 二. ctype.h 三. errno.h 四. float.h 五.limits.h 六. locale.h 一. assert.h 源码…

基于梯度提升树回归模型的房地产价格估计

目录 1. 作者介绍2. 梯度提升树回归算法介绍2.1 算法原理2.2 算法讲解与分析 3. 实验过程3.1 数据集介绍3.2 代码介绍3.3 完整代码实现3.4 测试结果 参考文献 1. 作者介绍 雷强&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2023级研究生 研究方向&#xff…

论文精读--Swin Transformer

想让ViT像CNN一样分成几个block&#xff0c;做层级式的特征提取&#xff0c;从而使提取出的特征有多尺度的概念 Abstract This paper presents a new vision Transformer, called Swin Transformer, that capably serves as a general-purpose backbone for computer vision. …

对人脸图像进行性别和年龄的判断

判断性别和年龄 导入必要的库加载预训练的人脸检测模型加载预训练的性别和年龄识别模型定义性别和年龄的标签列表创建Tkinter窗口&#xff1a;定义选择图片的函数&#xff1a;创建一个按钮&#xff0c;用于打开文件选择对话框定义显示图片的函数创建预测性别和年龄的函数创建预…

vue2 bug求助!!!(未解决,大概是浏览器缓存的问题或者是路由的问题)

我的vue2项目出现了一个超级恶心的bug 过程&#xff1a; 1 操作流程&#xff1a;页面a点击a标签->到页面b->页面b用户退出刷新页面->点击浏览器的返回按钮返回上一页 2 结果&#xff1a;返回页面后页面没有刷新导致用户名还显示着&#xff0c;页面没有发生任何变化&a…

基于Pytorch框架的深度学习ShufflenetV2神经网络十七种猴子动物识别分类系统源码

第一步&#xff1a;准备数据 17种猴子动物数据&#xff1a; self.class_indict ["白头卷尾猴", "弥猴", "山魈", "松鼠猴", "叶猴", "银色绒猴", "印度乌叶猴", "疣猴", "侏绒"…

​研学活动方案模板,详细制作步骤!​

研学活动&#xff0c;作为教育实践的重要组成部分&#xff0c;为我们的学生提供了一个广阔的学习平台。在这个平台上&#xff0c;学生们能够将书本上的知识与现实世界紧密联系起来&#xff0c;通过实践探索来培养能力。但对于咱们老师来说&#xff0c;学校组织研学活动要考虑到…

“雪糕刺客”爆改“红薯刺客”,钟薛高给了消费品牌哪些启示?

夏日袭来&#xff0c;一支价格高昂却让人眼前一亮的雪糕&#xff0c;曾一度成为市场热议的焦点。然而&#xff0c;随着消费者对性价比的日益关注&#xff0c;曾经的“雪糕刺客”钟薛高&#xff0c;其创始人林盛近期以直播带货红薯开启他的还债之路&#xff0c;高打情怀“直播自…

STM32学习和实践笔记(33):待机唤醒实验

1.STM32待机模式介绍 很多单片机具有低功耗模式&#xff0c;比如MSP430、STM8L等&#xff0c;我们的STM32也不例外。默认情况下&#xff0c;系统复位或上电复位后&#xff0c;微控制器进入运行模式。在运行模式下&#xff0c;HCLK 为CPU提供时钟&#xff0c;并执行程序代码。这…

java配置文件解析yml/xml/properties文件

XML 以mybatis.xml:获取所有Environment中的数据库并连接session为例 import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException;import javax.xml.parsers.DocumentBuilder; impo…

springboot基本使用十一(自定义全局异常处理器)

例如&#xff1a;我们都知道在java中被除数不能为0&#xff0c;为0就会报by zero错误 RestController public class TestController {GetMapping("/ex")public Integer ex(){int a 10 / 0;return a;}} 打印结果&#xff1a; 如何将这个异常进行处理&#xff1f; 创…