基于C++实现家谱管理系统

1. 分析

1.1 背景分析

家谱管理系统是一个社会不可缺少的部分,它对于家族中的各个人、社会、历史学家等来说都至关重要,所以一个良好的家谱管理系统应该能够为用户提供充足的信息和功能。家谱系统对于家族和历史学家研究家族的发展有极其重要的作用。随着家族人数的日益庞大,如何管理如此庞大的数据显得极为复杂,传统的手工管理工作量大且容易出错。

随着计算机科学技术的不断成熟,使用计算机对家谱管理进行管理,具有手工管理所无法比拟的优势。这些优点能够极大地提高家族和社会的效率,也是社会走向信息化、科学化、国际化的重要条件。因此,开发一套家谱管理系统具有十分重要的意义。

1.2 功能分析

作为一个最简易的家谱管理系统,首先应该允许用户完善家谱,并能简单的输出整个家谱。

其次,家谱管理系统还应该具有添加成员、解散局部家庭、更改家庭成员姓名功能,以保证家庭成员可以随时更改自己的家庭信息。最后,家谱管理系统软件还应该确保软件可以正常关闭,以及如果用户输入的数据有问题的时候可以做出简单的检查和提示。

综上所述,一个家谱管理系统至少应该具有完善家谱、添加成员、解散局部家庭、更改家庭成员姓名、输出家谱、健壮性的检测等功能。

2. 设计

2.1 数据结构设计

如上功能分析所述,该系统具有明显的树形结构,因此考虑使用树作为数据结构。同时,由于每一个父亲的孩子数量是不确定的,因此不能简单的只设置 leftChile 和 rightChild 指针,本系统采用链表作为数据结构保存每个父节点的所有孩子的指针。

同时将每个人作为类封装起来,可以方便的修改每个人的属性,例如想增加每个人的年龄这一信息,可以直接在 People 类中增加一个 int 类型的变量表示人的年龄。

2.2 类结构设计

  • Pelople 类用于储存成员信息
  • TreeNode 类存储树中的结点
  • Genealogy 类作为家谱类,相当于树这个数据结构

2.3 成员与操作设计

成员信息类(People)

公有成员:

string name;		//姓名

考生信息的构造函数:

People() = default;
People(const string &buf);People::People(const string & buf)
:name(buf) {}

重载运算符:

bool operator ==(const People &buf);	//判断两个成员是否是同一个人
bool People::operator==(const People & buf)
{return (this->name == buf.name);
}

树中的结点类(TreeNode)

公有成员:

struct People data;		//成员信息
list<TreeNode *> Child;	//孩子链表

友元:

friend istream& operator>>(istream &is, TreeNode &buf);			//重载运算符用于读入树中的结点friend ostream& operator<<(ostream &os, const TreeNode &buf);	//重载运算符用于输出树中的结点istream & operator>>(istream & is, TreeNode & buf)
{is >> buf.data.name;return is;
}ostream & operator<<(ostream & os, const TreeNode & buf)
{os << buf.data.name;return os;
}

构造函数:

TreeNode() = default;
TreeNode(const People &buf);
TreeNode::TreeNode(const People & buf): data(buf)
{this->Child.clear();
}

重载运算符:

bool operator !=(const TreeNode &buf);		//判断两个树中的结点是否不相等
bool TreeNode::operator!=(const TreeNode & buf)
{return !(this->data == buf.data);
}

家谱类(Genealogy)

私有成员:

TreeNode * _root = NULL;		//家谱的根结点

公有操作:

Genealogy() = default;
Genealogy(const string &buf);
~Genealogy();
bool isEmpty() {return _root == NULL;    //判断家谱是否为空
}
void DestroyGenealogy(TreeNode *root);		//销毁树中所有结点
void showRoot();								//输出根结点
void showFirstGenChild(const TreeNode *root);	//输出第一代子孙
void showTree();								//分层输出树中所有结点
TreeNode *findPeople(TreeNode *root, const string &name);	//寻找某个人是否在家谱中
TreeNode *findParent(TreeNode *root, const TreeNode *buf);	//寻找某个人的父结点
void BuildFamily();			//建立家庭
void addChild();			//添加家庭成员
void removeFamily();		//解散家庭
void changeName();			//更改家庭成员姓名

2.4 系统设计

系统首先对屏幕进行初始化,完成对家谱树的创建和输入数据工作,然后根据用户所输入的操作码(OpCode)执行家谱类 GenTree 对应的成员函数。

3. 实现

3.1 完善家谱功能的实现

3.1.1 完善家谱功能流程图

在这里插入图片描述

3.1.2 完善家谱功能核心代码

void Genealogy::BuildFamily()
{string name;cout << "请输入要建立家庭的人的姓名: ";cin >> name;TreeNode *move = findPeople(_root, name);if (move)
//如果存在该待创建家庭的结点{int size;cout << "请输入" << *move << "的儿女人数: ";cin >> size;cout << "请依次输入" << *move << "的儿女的姓名: ";for (int i = 0; i < size; ++i){cin >> name;move->Child.push_back(new TreeNode(People(name)));	//依次添加在孩子数组后面assert(move->Child.back() != NULL);}showFirstGenChild(move);		//输出创建家庭后 该结点的第一代子孙}else{cout << "家谱中没有该家庭成员!" << endl;}
}

3.1.3 完善家谱功能截屏示例

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

3.2 添加家庭成员功能的实现

3.2.1 添加家庭成员功能流程图

在这里插入图片描述

3.2.2 添加家庭成员功能核心代码

void Genealogy::addChild()
{string name;cout << "请输入要添加儿子(或女儿)的人的姓名: ";cin >> name;TreeNode *parent = findPeople(_root, name);if (parent)
//如果存在该 待添加儿子的结点{TreeNode *fresh = new TreeNode;		//为添加的孩子新开辟空间assert(fresh != NULL);cout << "请输入" << *parent << "新添加的儿子(或女儿)的姓名: ";cin >> *fresh;parent->Child.push_back(fresh);		//添加到当前结点的孩子数组后面this->showFirstGenChild(parent);	//输出添加儿子后 该结点的第一代子孙}else{cout << "家谱中没有该家庭成员!" << endl;}
}

3.2.3 添加家庭成员功能截屏示例

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

3.3 解散局部家庭功能的实现

3.3.1 解散局部家庭功能流程图

在这里插入图片描述

3.3.2 解散局部家庭功能核心代码

void Genealogy::removeFamily()
{string name;cout << "请输入要解散家庭的人的姓名: ";cin >> name;TreeNode *move = findPeople(_root, name);if (move == _root)
//如果解散的根结点特殊处理{cout << "要解散家庭的人是: " << *move << endl;this->showFirstGenChild(move);		//输出下一代子孙DestroyGenealogy(_root);delete _root;_root = NULL;}else if (move)
//如果存在该待解散家庭的结点{cout << "要解散家庭的人是: " << *move << endl;this->showFirstGenChild(move);		//输出下一代子孙this->DestroyGenealogy(move);		//递归destroy函数, 递归的删除该结点作为根结点的子树
//先在parent的孩子数组中把他移除TreeNode *parent = findParent(_root, move);parent->Child.erase(find(parent->Child.begin(), parent->Child.end(), move));
//再释放该结点delete move;move = NULL;}else{cout << "家谱中没有该家庭成员!" << endl;}
}

3.3.3 解散局部家庭功能截图示例

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

3.4 更改家庭成员姓名功能的实现

3.4.1 更改家庭成员姓名功能流程图

在这里插入图片描述

3.4.2 更改家庭成员姓名功能核心代码

void Genealogy::changeName()
{string name;cout << "请输入要更改姓名的人的目前姓名: ";cin >> name;TreeNode *move = findPeople(_root, name);if (move)
//如果存在该 待更改姓名的结点{cout << "请输入更改后的姓名: ";cin >> *move;cout << name << "已更名为" << *move << endl;}else{cout << "家谱中没有该家庭成员!" << endl;}
}

3.4.3 更改家庭成员姓名功能截屏示例

在这里插入图片描述

在这里插入图片描述

3.5 输出家谱功能的实现

3.5.1 输出家谱功能流程图

在这里插入图片描述

3.5.2 输出家谱功能核心代码

输出某节点的下一代

void Genealogy::showFirstGenChild(const TreeNode *root)
{cout << root->data.name << "的第一代子孙是: ";for (const auto& buf : root->Child)
//循环当前结点的孩子数组{cout << *buf << "	";}cout << endl;
}

输出家谱的整棵树

void Genealogy::showTree()
{if (isEmpty())
//家谱为空时特殊处理{cout << "家谱为空!" << endl;return;}queue<TreeNode *> Q;				//层次化访问工作队列push(this->_root);				//压入根结点TreeNode buf(People(ERRORNAME));	//定义分隔结点TreeNode move;while (!Q.empty()){push(&buf);			//压入用于分隔的分隔结点move = *(Q.front());	//取出队列头结点while (move != buf)		//当头上结点不是分隔结点时循环输出{pop();for (const auto& elem : move.Child)
//将当前结点的所有孩子压入队列{push(elem);}if (move != buf){cout << move << "  ";}move = *(Q.front());}pop();				//将当前层次的分隔结点取出cout << endl;}
}

3.5.3 输出家谱功能截屏示例

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

3.6 销毁家谱的实现

3.6.1 销毁家谱流程图

在这里插入图片描述

3.6.2 销毁家谱核心代码

Genealogy::~Genealogy()
{DestroyGenealogy(_root);		//调用destroy函数, 一次释放树中所有结点delete _root;	//释放根结点_root = NULL;
}
void Genealogy::DestroyGenealogy(TreeNode *root)
{if (root->Child.empty())
//如果该结点为叶子结点 -> 孩子数组为空{delete root;	//释放该结点root = NULL;}else{for (auto &bufNode : root->Child){DestroyGenealogy(bufNode);
//递归调用destroy函数, 对孩子数组中的每一个元素执行销毁操作}}
}

3.6.3 销毁家谱截屏示例

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

3.7 总体系统的实现

3.7.1 总体系统流程图

在这里插入图片描述

3.7.2 总体系统核心代码

cout << "**             " << "家谱管理系统" << "                 **" << endl;
cout << "==============================================" << endl;
cout << "**             " << "请选择要执行的操作: " << "         **" << endl;
cout << "**             " << "A --- 完善家谱" << "               **" << endl;
cout << "**             " << "B --- 添加家庭成员" << "           **" << endl;
cout << "**             " << "C --- 解散局部家庭" << "           **" << endl;
cout << "**             " << "D --- 更改家庭成员姓名" << "       **" << endl;
cout << "**             " << "E --- 退出程序" << "               **" << endl;
cout << "**             " << "S --- 输出家谱" << "               **" << endl;
/*建立家谱*/
cout << "首先建立一个家谱!" << endl;
string buf;
cout << "请输入祖先的姓名: ";
cin >> buf;
Genealogy GenTree(buf);
GenTree.showRoot();
/*用户操作*/
char OpCode;
while (1)
{cout << endl << "请输入要执行的操作: ";cin >> OpCode;if (OpCode == 'E') {break;}switch (OpCode){case 'A':{GenTree.BuildFamily();break;}case 'B':{GenTree.addChild();break;}case 'C':{GenTree.removeFamily();break;}case 'D':{GenTree.changeName();break;}case 'S':{GenTree.showTree();break;}default:{cout << "请输入大写字母A~E!" << endl;break;}}
}

3.7.3 总体系统截屏示例

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

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【jackson】自定义字段注解完成序列化逻辑

目录 背景本文开发环境介绍新建一个注解新建一个JavaBean新建一个JsonSerializer新建一个AnnotationIntrospector单元测试总结 背景 Spring默认的JSON序列化工具使用的是jackson&#xff0c;GitHub项目地址: https://github.com/FasterXML/jackson 我们在处理前后端接口交互的…

Amazon CloudFront 部署小指南(五)- 使用 Amazon 边缘技术优化游戏内资源更新发布...

内容简介 游戏内资源包括玩家的装备/弹药/材料等素材&#xff0c;对游戏内资源的发布和更新是游戏运营商的一个常规业务流程&#xff0c;使用频率会十分高&#xff0c;所以游戏运营商希望该流程可以做到简化和可控。针对这个需求&#xff0c;我们设计了 3 个架构&#xff0c;面…

Adobe2021/20年11月更新推送

以下更新vposy带来的Adobe11月份更新推送&#xff0c;是部分小版本BUG修复更新&#xff0c;安装新版的建议更新一下以获取更好的使用体验&#xff0c;软件获取方式位于为文末。 版本更新简要 Photoshop 22.0.1 此更新包含对多个崩溃问题和工作流程错误的修复 After Effects…

Adobe 系列软件安装及激活异常解决方法

很多小伙伴安装 Adobe 的软件出现这样那样的的异常&#xff0c;希望通过这篇文章&#xff0c;可以帮大家解决问题。 安装前需要做什么&#xff1f; 如果安装过其它版本的 Adobe 软件&#xff0c;请使用 Adobe 官网卸载工具Adobe Creative Cloud Cleaner Tool卸载干净&#xf…

Adobe2021 4月份更新推送

前言 今天又又又给各位带来了vposy大神河蟹制作的Adobe 4月份更新推送 小编整理了一下供大家查阅&#xff0c;追新版本的可以更新一下&#xff0c;以获取更好的使用体验 大多更新都是提升稳定性修复Bug…… 配置要求 新版本整体对系统要求最低为Win10的1903版本&#xff0…

【EM算法推导】

# 一、必备的基础知识 EM算法用到了大量的概率论与数理统计的知识&#xff0c;必须对基础有一定掌握才能完成EM算法的推导。 ## 1.1 最大似然估计 思想&#xff1a;我们观测到了一组样本&#xff0c;为什么我们能观测到这一组样本呢&#xff1f;因为这一组样本出现的概率比较大…

18-有假币

题目 居然有假币&#xff01; 现在猪肉涨了&#xff0c;但是农民的工资却不见涨啊&#xff0c;没钱怎么买猪肉啊。nowcoder这就去买猪肉&#xff0c;结果找来的零钱中有假币&#xff01;&#xff01;&#xff01;可惜nowcoder 一不小心把它混进了一堆真币里面去了。只知道假币…

Java项目-苍穹外卖-Day03

员工分页查询功能实现 需求分析和设计 代码开发 先设计类 将对应分页查询的传参类以及结果类进行封装 对应真正返回的为Result<PageResult>Controller /**** param employeePageQueryDTO* return*/GetMapping("/page")ApiOperation("员工分页查询&qu…

什么是CSS Grid布局?什么是Flexbox布局?它们两者有什么不同?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS Grid布局⭐ Flexbox布局⭐ 不同之处⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web…

QT 如何绘制圆形进度条

QT绘制圆形进度条&#xff0c;不同于QPainterPath方式&#xff0c;直接使用 drawArc 函数效果也是出奇的好&#xff01; void Widget::paintEvent(QPaintEvent *event) {QPainter p(this);p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);QRect rc t…

android实现圆形进度条

/*** date:2021/1/4 0004* author:wsm (Administrator)* funcation:圆形进度条控件*/public class CircleProgressView extends View {private Paint mBackPaint, mProgPaint; // 绘制画笔private RectF mRectF; // 绘制区域private int[] mColorArray; // 圆环渐变色…

uniapp圆形进度条

插件下载地址&#xff1a;https://ext-resource-aliyun.dcloud.net.cn/marketplace/206a8e50-63cb-11ec-8e77-a3fa77cd6ec0/1.1.2/plugin.zip?v1668747036 一、下载并解压&#xff0c;复制到uniapp的components下 二、使用 import导入组件 import circleProgressBar from /…

超简单的Android圆形进度条

效果图&#xff1a; 代码优化/简化、教科书级别注释、复制粘贴即可用 代码&#xff1a; package com.zistone.factorytest0718.view;import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; impor…

Android 绘制圆形进度条

Android 绘制圆形进度条 最近项目上有一些需求&#xff0c;需要绘制圆形的进度条满足设计上和交互上的需求&#xff1a; 实现思路 在画布上直接绘制View&#xff0c;需要了解一下几点 1.需要画一个圆 2.圆圈上有不同进度的颜色 3.圆圈中有进度数字的展示 4.圆圈中间还…

纯css制作圆形进度条

效果图大概是这样的 第一步 先定义出一个方形盒子 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>…

实现一个圆形进度条(vue)

实现方式&#xff1a;首先是用svg画两个圆&#xff0c;同圆心同半径的两个圆&#xff0c;然后把颜色都设置成透明&#xff0c;利用圆的边框来实现。给两个圆设置相同的边框宽度&#xff0c;并且设置颜色&#xff08;设置一个透明&#xff0c;一个有颜色&#xff09;&#xff1b…

药都银行冲刺上交所:年营收22.78亿 古井集团是股东

雷递网 雷建平 5月1日 亳州药都农村商业银行股份有限公司&#xff08;简称&#xff1a;“药都银行”&#xff09;日前递交招股书&#xff0c;准备在上交所主板上市。 药都银行计划募资16.38亿元。 年营收22.78亿 药都银行坐落于世界中医药之都——亳州市&#xff0c;于2005年12…

自贸港首家公务机公司海航金鹿商务正式启动运营

日前&#xff0c;海航集团旗下金鹿公务在海口设立公务机总部 -- 金鹿商务航空有限公司&#xff08;简称&#xff1a;金鹿商务&#xff09;&#xff0c;已通过中国民用航空海南安全监督管理局运行审定&#xff0c;取得中国民用航空中南地区管理局颁发的运行规范。4月29日上午9时…

内网通朋友不在线

前段时间使用内网通发现同学老师的总是不在线&#xff0c;有时候改一下IP地址&#xff0c;又可以&#xff0c;后面才发现原来可以自己设置网段地址的 设置过程见下图&#xff1a; 输入老师的IP地址的前三位即可

基于html5在线学生学籍信息管理系统

随着高校人数越来越多&#xff0c;管理高校的学生人数成为难题&#xff0c;如何更好的管理高校的入学人数&#xff1f;通过学籍的管理方式可以很好的将各年级&#xff0c;各个院校&#xff0c;各个专业的学生进行统一的管理&#xff0c;对不同的学生分门别类&#xff0c;学籍管…