『管理系统?』▻▻看这250行代码就够了◅◅

引言

不知道大家刚接触"『管理系统』"这个词的时候是怎么想的,我反正认为这是一个很高大上的东西,实现起来一定超难。结果后面看到了运行结果,有那么一丢丢"请以实物为准"的感觉,这里先把我这个项目的效果图放在下面。

这是用C++写出来的,其实用C语言写出来的也差不多。

如果看到这里,你还是感兴趣的话,那么就继续看下去吧,后面我会描述一下设计思路并把程序代码贴出来。

设计思路

做任何事情总要有个起因,我当然也不是无缘无故的就想搞这个,哪怕它很常见,这其实是我的一次作业,先把作业的题目放在下面,这样也可以明确需求。

建立一个结点包括职工的编号、年龄和性别的单向链表,分别定义函数完成以下功能:

(1)遍历该链表输出全部职工信息;

(2)分别统计男、女职工的人数;

(3)在链表尾部插入新职工结点;

(4)删除指定编号的职工结点;

(5)删除年龄在60岁以上的男性职工或55岁以上的女性职工结点,并保存在另一个链表中。

要求:用主函数建立简单菜单选择,并测试程序。

看到问题后,我的第一想法就是自定义五个函数分别实现这五个功能,在主函数的调用下实现管理系统。

这一题很明显需要使用链表,所以我创建了一个结构体类型用来存放职工的编号、年龄、性别以及指向下一节点的指针,然后声明自定义函数。在完成这些后,我就开始编写主函数了,首先当然是建立一个头指针指向空,然后在do...while循环中显示菜单,使用switch根据用户输入的数字调用相关函数实现相应功能,或退出程序。

先对链表的一些知识明确一下:

这里先把这部分的代码放在下面,有一些没解释到的代码暂时用不到,这是程序基本功能实现后优化输出的,后面会解释,暂时先忽略就行了。

c 复制代码
#include <iostream>

using namespace std;

struct information {
	int id;
	int age;
	string sex;
	information* next;
}*s,*p,*new_s,*new_p;
information* new_head = NULL;
int help_judge = 0;

void all_out(information*);
void sex_num_out(information*);
void last_inset(information* &);
void my_delete(information*&);
void classify(information* &);

int main()
{
	information* head;
	head = NULL;
	int select;
	do
	{
		cout << "************职工管理系统**********" << endl << endl;
		cout << "(0)           退出" << endl;
		cout << "(1)      显示全部信息" << endl;
		cout << "(2)         性别统计" << endl;
		cout << "(3)      新建职工信息" << endl;
		cout << "(4)      删除职工信息" << endl;
		cout << "(5)    将退休职工信息分离" << endl;
		cout << endl << "请输入相应功能的数字:" << endl;
		cin >> select;
		{
			switch (select)
			{
			case 1:
				all_out(head);
				break;
			case 2:
				sex_num_out(head);
				break;
			case 3:
				last_inset(head);
				break;
			case 4:
				my_delete(head);
				break;
			case 5:
				classify(head);
				break;
			default:
				cout << "输入错误,请重新输入:" << endl;
			}
		}
	} while (select);
}

具体实现

功能1------遍历链表

这一个函数的关键在于对头指针的使用,我们知道头指针应该始终指向链表的起始位置,但是我们在这一步需要使用头指针进行遍历,所以就需要创建一个形参头指针用来指向和实际上的头指针相同的地方,这其实就相当于有两个指针指向了同一个位置,形参头指针在函数结束后被清除,实际上的头指针没有任何变化。

下面代码供参考:

bash 复制代码
void all_out(information* head)
{
	if (help_judge == 0)
	{
		cout << "还没有录入信息,表格为空" << endl;
		cout << endl << "返回菜单" << endl;
		return;
	}
	cout << "    职工信息表   " << endl;
	if (help_judge == 3)
		cout << endl << "职工全部信息为:" << endl;
	else
		cout << endl << "未退休职工信息为:" << endl;
	while (head)
	{
		cout << "id = " << head->id << "   age = " << head->age << "   sex = " << head->sex << endl;
		head = head->next;
	}
	if(help_judge == 5)
		cout << "退休职工信息为:" << endl;
	while (new_head)
	{
		cout << "id = " << new_head->id << "   age = " << new_head->age << "   sex = " << new_head->sex << endl;
		new_head = new_head->next;
	}
	cout << endl << "返回菜单" << endl;
}

功能2------性别统计

这个函数的关键和1中的一样,这里就不在赘述。在明确这一点后,我们只需要定义两个变量用来存放男职工和女职工的人数就可以了,下面同样给出代码:

c 复制代码
void sex_num_out(information* head)
{
	cout << "       职工性别统计表" << endl;

	int sum_men = 0, sum_women = 0;
	while (head)
	{
		if (head->sex == "男")
			sum_men++;
		else
			sum_women++;
		head = head->next;
	}
	cout << "男职工人数为:" << sum_men << endl;
	cout << "女职工人数为:" << sum_women << endl;
	cout << endl << "返回菜单" << endl;
}

功能3------录入信息

一个系统最基本的功能就是输入信息了。

我们在输入信息的时候需要开辟一个空间用来存放数据,将信息输入到这个空间然后令该空间指向空,在确认信息输入合法后,判断头指针是否为空,如果为空,就令头指针指向该空间,尾指针也指向该空间;如果不为空,就令当前链表的尾部指向该空间,然后尾指针指向该空间。下面给出代码供参考:

c 复制代码
void last_inset(information*& head)
{
	help_judge = 3;
	cout << "开始录入新职工信息:" << endl;
	s = new information;
	cout << "id = ???" << "   age = ???" << "   sex = ???" << endl;
	cin >> s->id >> s->age>> s->sex;
	if (s->sex != "男" && s->sex != "女")
	{
		cout << "Sorry,性别输入错啦,程序返回菜单" << endl;
		delete s;
		return;
	}
	s->next = NULL;
	information *temp_head = head;
	while (temp_head)
	{
		if (s->id == temp_head->id)
		{
			cout << "id重复,返回菜单" << endl;
			delete s;
			return;
		}
		temp_head = temp_head->next;
	}

	if (head == NULL)
	{
		head = s;
		p = head;
		cout << endl << "返回菜单" << endl;
		return;
	}
	else
	{
		p->next = s;
		p = p->next;
		cout << endl << "返回菜单" << endl;
		return;
	}
}

功能4------删除信息

在这里还是需要遍历链表,寻找要删除的职工编号,我们在创建链表的时候考虑到是不是头指针的情况,在这里同样也要分两种情况。

代码不长,还是挺通俗易懂的:

ini 复制代码
void my_delete(information*& head)
{
	if (head == NULL)
	{
		cout << "删除失败,原因是你可能还没有输入信息,请输入后再尝试该功能,程序返回菜单" << endl << endl;
		return;
	}
	cout << "   删除职工信息" << endl;
	information* temp_head_1 = head->next;
	information* temp_head_2 = head;
	int delete_id;
	cin >> delete_id;
	while (temp_head_2)
	{
		if (delete_id == head->id)
		{
			head = head->next;
			delete temp_head_2;
			cout << "已删除" << endl;
			cout << endl << "返回菜单" << endl;
			return;
		}

		if (delete_id == temp_head_1->id)
		{
			s = temp_head_1;
			temp_head_1 = temp_head_1->next;
			temp_head_2->next = temp_head_1;
			delete s;
			cout << "已删除" << endl;
			cout << endl << "返回菜单" << endl;
			return;
		}
		temp_head_1 = temp_head_1->next;
		temp_head_2 = temp_head_2->next;
	}
	cout << "id没找到,返回菜单" << endl;
	return;
}

功能5------分离信息

现在我们终于要进行最后一个功能了。

在这一步,函数接收一个指向information结构体链表头的指针作为参数,这里使用引用运算符将真正的头指针传了过来,因为我们要对链表进行修改。

首先,函数检查输入的链表头是否为空,如果为空,则提示用户输入信息后再尝试该功能,并返回菜单。然后,函数遍历链表中的每个节点,根据节点的年龄和性别进行分类。如果当前节点的年龄大于等于60且性别为男,或者年龄大于等于55且性别为女,将其从原链表中移除,并创建一个新的节点,将其添加到新链表的末尾。如果当前节点不满足以上条件,继续遍历链表。

遍历完成后,输出完成信息,并返回菜单。

ini 复制代码
void classify(information*& head)
{
	cout << "开始分离退休职工信息" << endl;
	if (head == NULL)
	{
		cout << "分离失败,原因是你可能还没有输入信息,请输入后再尝试该功能,程序返回菜单" << endl << endl;
		return;
	}
	help_judge = 5;
	information* temp_head_1 = head->next;
	information* temp_head_2 = head;
	while (temp_head_1 || temp_head_2)
	{  
		if ((head->age >= 60 && head->sex == "男") || (head->age >= 55 && head->sex == "女"))
		{
			s = head;
			if (temp_head_2)
				temp_head_2 = temp_head_2->next;
			if (temp_head_1)
				temp_head_1 = temp_head_1->next;
			head = temp_head_2;
			new_s = new information;
			new_s->id = s->id;
			new_s->age = s->age;
			new_s->sex = s->sex;
			new_s->next = NULL;
			delete s;
			if (new_head == NULL)
			{
				new_head = new_s;
				new_p = new_s;
			}
			else
			{
				new_p->next = new_s;
				new_p = new_p->next;
			}
		}
		else if ((temp_head_1) && ((temp_head_1->age >= 60 && temp_head_1->sex == "男") || (temp_head_1->age >= 55 && temp_head_1->sex == "女")))
		{
			s = temp_head_1;
			temp_head_2->next = temp_head_1->next;
			if (temp_head_1)
				temp_head_1 = temp_head_1->next;
			new_s = new information;
			new_s->id = s->id;
			new_s->age = s->age;
			new_s->sex = s->sex;
			new_s->next = NULL;
			delete s;
			if (new_head == NULL)
			{
				new_head = new_s;
				new_p = new_s;
			}
			else
			{
				new_p->next = new_s;
				new_p = new_p->next;
			}
		}
		else
		{
			if (temp_head_2)
				temp_head_2 = temp_head_2->next;
			if (temp_head_1)
				temp_head_1 = temp_head_1->next;
		}
	}
	cout << endl << "完成退休职工信息的分离,返回菜单" << endl << endl;
}

补充

有一些没解释的代码是因为不是核心功能,它只是用来方便输出提高用户体验,也很通俗易懂,相信读者朋友看到这里已经对链表知识掌握的相当可以了,文章到这里也结束了,感谢阅读!

相关推荐
汉克老师1 小时前
GESP2024年3月认证C++六级( 第三部分编程题(1)游戏)
c++·学习·算法·游戏·动态规划·gesp6级
闻缺陷则喜何志丹1 小时前
【C++图论】2685. 统计完全连通分量的数量|1769
c++·算法·力扣·图论·数量·完全·连通分量
利刃大大1 小时前
【二叉树深搜】二叉搜索树中第K小的元素 && 二叉树的所有路径
c++·算法·二叉树·深度优先·dfs
幸好我会魔法1 小时前
人格分裂(交互问答)-小白想懂Elasticsearch
大数据·spring boot·后端·elasticsearch·搜索引擎·全文检索
SomeB1oody2 小时前
【Rust自学】15.2. Deref trait Pt.1:什么是Deref、解引用运算符*与实现Deref trait
开发语言·后端·rust
何中应2 小时前
从管道符到Java编程
java·spring boot·后端
Mryan20052 小时前
LeetCode | 不同路径
数据结构·c++·算法·leetcode
SummerGao.2 小时前
springboot 调用 c++生成的so库文件
java·c++·.so
情深不寿3172 小时前
C++----STL(list)
开发语言·c++
m0_742155432 小时前
linux ——waitpid介绍及示例
linux·c++·学习方法