学生信息管理系统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;}

结果展现

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

生成式 AI——ChatGPT、Dall-E、Midjourney 等算法理念探讨

1.概述 艺术、交流以及我们对现实世界的认知正在迅速地转变。如果我们回顾人类创新的历史&#xff0c;我们可能会认为轮子的发明或电的发现是巨大的飞跃。今天&#xff0c;一场新的革命正在发生——弥合人类创造力和机器计算之间的鸿沟。这正是生成式人工智能。 生成模型正在模…

【遂愿赠书 - 1期】:安恒“网安三剑客”-大模型时代下的网络安全实战指南

文章目录 一、图书背景二、网安实战宝典2.1《内网渗透技术》2.2《渗透测试技术》2.3《Web应用安全》 三、校企合作&#xff0c;产学研结合四、大模型时代的数字安全五、 网络安全无小事 一、图书背景 大模型风潮已掀起&#xff0c;各大巨头争相入局&#xff0c;从ChatGPT到Sor…

研学活动报名收集材料怎么写?教程来了!

研学活动作为学校教育的重要组成部分&#xff0c;不仅能够拓宽学生的视野&#xff0c;还能促进家校沟通。学生们报名还是十分积极踊跃的&#xff0c;然而研学活动报名收集材料该怎么写却困扰着不少老师&#xff0c;其实只需要把姓名和联系方式等收集全就可以了&#xff0c;主要…

Go Modules 使用

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

遥感卫星影像处理流程

当空中的遥感卫星获取了地球数字影像&#xff0c;并传回地面&#xff0c;是否工作就结束了&#xff1f;答案显然是否定的&#xff0c;相反&#xff0c;这正是遥感数字图像处理工作的开始。 遥感数字图像&#xff08;Digital image&#xff0c;后简称“遥感影像”&#xff09;是…

FTP

文章目录 概述主动模式和被动模式的工作过程注意事项 概述 文件传输协议 FTP&#xff08;File Transfer Protocol&#xff09;在 TCP/IP 协议族中属于应用层协议&#xff0c;是文件传输标准。主要功能是向用户提供本地和远程主机之间的文件传输&#xff0c;尤其在进行版本升级…

数据分析每周挑战——心衰患者特征数据集

这是一篇关于医学数据的数据分析&#xff0c;但是这个数据集数据不是很多。 背景描述 本数据集包含了多个与心力衰竭相关的特征&#xff0c;用于分析和预测患者心力衰竭发作的风险。数据集涵盖了从40岁到95岁不等年龄的患者群体&#xff0c;提供了广泛的生理和生活方式指标&a…

【Linux终端探险】:从入门到熟练,玩转基础命令的秘密(二)

文章目录 &#x1f680;Linux基础命令&#xff08;二&#xff09;&#x1f308;1. 寻找目录/文件命令⭐2. 创建文件命令&#x1f44a;3. 网络接口查询命令❤️4. 打包命令&#x1f4a5;5. 解压命令 上期回顾&#xff1a; &#x1f525;&#x1f525;&#x1f525;【Linux终端探…

CMakeFile.txt通过sysroot方式后生成makefile报错

报错信息如下&#xff1a; -- The C compiler identification is unknown -- The CXX compiler identification is unknown -- Check for working C compiler: /home/xj/asm/host/bin/aarch64-buildroot-linux-gnu-gcc -- Check for working C compiler: /home/xj/asm/host/bi…

英伟达GeForce发布《星球大战:亡命之徒》宣传片,8月30日开售

易采游戏网6月3日消息&#xff1a;英伟达GeForce近日发布了一款激动人心的宣传片&#xff0c;展示了备受期待的游戏大作《星球大战&#xff1a;亡命之徒》。该宣传片不仅展现了游戏的华丽画面和引人入胜的故事情节&#xff0c;还重点介绍了支持NVIDIA DLSS 3.5、光线追踪和Refl…

工业级物联网边缘网关解决方案-天拓四方

随着工业4.0时代的到来&#xff0c;越来越多的企业开始寻求智能化升级&#xff0c;以提高生产效率、降低运营成本并增强市场竞争力。然而&#xff0c;在实际的转型升级过程中&#xff0c;许多企业面临着数据孤岛、设备兼容性差、网络安全风险高等问题&#xff0c;这些问题严重制…

mybatis+vue2前后端分离

目录 后端样例目录结构&#xff1a; ​编辑pom.xml文件 连接数据库信息&#xff08;mysql&#xff09;&#xff1a; config.properties 全部配置文件&#xff1a;mybatis-config.xml 包装sqlSessionFactory&#xff08;减少代码耦合&#xff09; 实体类food: 编写mapper.…

SpringCloud网关-gateway

一 什么是网关&#xff1f;为什么选择 Gateway? 网关功能如下&#xff1a; 身份认证和权限校验服务路由、负载均衡请求限流 在 Spring Cloud 中网关的实现包含两种&#xff1a; Gateway&#xff08;推荐&#xff09;&#xff1a;是基于 Spring5 中提供的 WebFlux &#xff…

仿真文件下载审核 有效保障HPC环境下的数据安全性

仿真文件在科学、工程和技术领域中具有重要性&#xff0c;所以确保仿真文件的安全性是非常重要的&#xff0c;特别是当这些文件包含敏感信息或涉及到关键的业务操作时。在获取仿真文件时&#xff0c;仿真文件下载审核这个流程也比较重要的。 审核仿真文件下载&#xff0c;你需要…

SAP 日期函数

1.计算两个时间的时间差&#xff1a;cl_abap_tstmp>subtract DATA: tstmp1 TYPE timestampl, tstmp2 TYPE timestampl, diff TYPE tzntstmpl. " P代表秒 " 获取两个时间戳 tstmp1 20230911183000. tstmp2 20230911153000. diff cl_abap_tstmp&g…

第 53 期:MySQL 创建了用户却无法登陆

社区王牌专栏《一问一实验&#xff1a;AI 版》全新改版归来&#xff0c;得到了新老读者们的关注。其中不乏对 ChatDBA 感兴趣的读者前来咨询&#xff0c;表达了想试用体验 ChatDBA 的意愿&#xff0c;对此我们表示感谢 &#x1f91f;。 目前&#xff0c;ChatDBA 还在最后的准备…

HBuilderX打包uni-app项目成安卓app

目录 1、下载Android 离线SDK 2、Android Studio导入工程 3、生成签名 3.1、进入到jdk bin目录下&#xff0c;输入cmd执行命令keytool -genkey -alias wxsalias -keyalg RSA -keysize 2048 -validity 36500 -keystore wxs.keystore 生成签名 3.2、查看签名密钥keytool -lis…

APP 备案步骤

一、打开阿里云备案系统平台&#xff1a;aliyunbaike.com/go/beian 二、开始备案 三、填写APP名称并进行信息校验 四、填写主办者基础信息和主办者负责人信息 五、填写互联网信息,android打包的APK包可直接上传识别信息&#xff0c;ios需要手动填写信息 公钥和证书SHA-1指纹如…

图片去手写软件有哪些?这三款值得一试!

图片去手写软件有哪些&#xff1f;在当今数字化时代&#xff0c;图片处理与编辑已成为我们日常生活中不可或缺的一部分。特别是在处理手写笔记、涂鸦或草图时&#xff0c;图片去手写软件发挥着至关重要的作用。它们能够帮助我们轻松去除图片中的手写内容&#xff0c;使图片更加…