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 总体系统截屏示例


基于C++实现家谱管理系统相关推荐

  1. 基于角色管理的简易家谱管理系统(C++/C(几乎都是C))2020-06-16

    一.课题内容和要求 (一)课题要求 家谱管理系统是查询家谱信息必不可少的一部分,利用家谱管理系统可以清楚的了解家族成员信息.该家谱管理系统是通过树来实现的.要求系统界面友好,易于操作. (二)课题要求 ...

  2. 基于C++实现(MFC界面)家谱管理系统【100010005】

    概述 题目的理解和分析: 该程序带有MFC界面,有树形控件来展示家庭成员的层次关系,还有list控件来浏览家庭成员信息.以及有对家谱成员的添加,删除,修改,查询功能,统计男女比例和求平均年龄,以及有对 ...

  3. mysql存储家庭成员信息_家谱管理系统的设计与实现(MyEclipse,MySQL)

    家谱管理系统的设计与实现(MyEclipse,MySQL)(任务书,开题报告,中期检查表,文献综述,毕业论文16700字,程序代码,MySQL数据库,答辩PPT) 家谱是现代人们怀旧的重要部分,因此, ...

  4. java计算机毕业设计基于Ssm学生信息管理系统源码+数据库+系统+lw文档+mybatis+运行部署

    java计算机毕业设计基于Ssm学生信息管理系统源码+数据库+系统+lw文档+mybatis+运行部署 java计算机毕业设计基于Ssm学生信息管理系统源码+数据库+系统+lw文档+mybatis+运 ...

  5. 基于JAVA宠物寄存管理系统计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA宠物寄存管理系统计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA宠物寄存管理系统计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

  6. 基于JAVA租车管理系统计算机毕业设计源码+系统+数据库+lw文档+部署

    基于JAVA租车管理系统计算机毕业设计源码+系统+数据库+lw文档+部署 基于JAVA租车管理系统计算机毕业设计源码+系统+数据库+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开发语言:Ja ...

  7. 基于Java毕业设计药品管理系统演示录像2021源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计药品管理系统演示录像2021源码+系统+mysql+lw文档+部署软件 基于Java毕业设计药品管理系统演示录像2021源码+系统+mysql+lw文档+部署软件 本源码技术栈: ...

  8. c++new时赋初值_基于ssm的客户管理系统 - C_you_again

    01 概述 一个简单的客户关系管理系统 管理用户的基本数据 客户的分配 客户的流失 已经客户的状态 02 技术 ssm + jdk1.8 + mysql5.4 03 运行环境 ecplice + jd ...

  9. python管理系统-基于Python实现用户管理系统

    基于Python的用户管理小系统,包含文件读写操作,实现了用户信息注册和登录的简单功能. class userLogReg: """ Created on 2018.11 ...

  10. java图书馆管理系统_六天写出来的基于Swing的图书管理系统你不来吐槽一下?

    前段时间学习完了MySQL和JDBC,想着自己做个东西实战一下,于是写了一个烂大街的图书管理系统...但好歹是自己一个人日夜兼程,硬着头皮做出来的还像样的东西,总结一手吧.看的人欢迎吐槽.我会从以下几 ...

最新文章

  1. 在asp.net中使用客户端脚本
  2. 【C语言】C语言实现面向对象编程之多态
  3. 论文浅尝 | EARL: Joint Entity and Relation Linking for QA over KG
  4. Python globals 函数 - Python零基础入门教程
  5. C#中Split用法
  6. 对话即平台:利用人工智能以及云平台打造你的智能机器人
  7. java删除相对路径文件夹_Java IO,io,文件操作,删除文件,删除文件夹,获取文件父级目录...
  8. Spring Web框架与Struts的区别
  9. php遍历目录与文件夹的多种方法详解
  10. 计算机仿真题液相色谱,液相色谱法
  11. 如何用MAYA 制作人物动画 使人物动作更加真实流畅
  12. Java程序员,你必须得知道并发编程概念
  13. SYN FLOOD攻击防范
  14. “拼多多和短视频极速版”,让我怎么吐槽你好呢!
  15. 第3章--Linux内核及内核编程
  16. 宝塔面板安装docker 再到docker容器里面安装宝塔
  17. AI遮天传 ML-初识决策树
  18. openCV学习系列1:我为什么要学习openCV,什么是openCV
  19. 用友软件防伪查询 - http://register.ufida.com.cn/chaxun.aspx
  20. 逻辑分区转化为主分区

热门文章

  1. python词组语义相似度_语义相似度
  2. C4D的几大主流渲染器!看完你就知道选择学习哪款了
  3. 查看自己电脑外网IP
  4. Yahoo的Spark实践
  5. 定位到excel最后一个非空单元格操作技巧,你一定要知道!(二)
  6. 查找Excel最后一个非空单元格的值,你会吗?(适用于数据加行时,一直引用最后一个非空单元格的值)
  7. ATFX:美联储会议纪要发布后,美元指数逼近105关口
  8. 开发QQ桌球瞄准器(2):创建项目添加主窗体
  9. 公开信息查询的一些方法,查征信,查婚姻状况,查询公开个人信息
  10. cos和sin转换公式