




已阅读5页,还剩20页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一.前言1 项目简介 家谱(或称族谱)是一种以表谱形式,记载一个以血缘关系为主体的家族世系繁衍和重要人物事迹的特殊图书体裁。家谱是中国特有的文化遗产,是中华民族的三大文献(国史,地志,族谱)之一,属珍贵的人文资料,对于历史学、民俗学、人口学、社会学和经济学的深入研究,均有其不可替代的独特功能。2系统功能 本项目对家谱管理进行简单的模拟,以实现查看祖先和子孙个人信息、插入家族成员、删除家族成员等功能。本项目的实质是完成对家谱成员信息的建立、查找、插入、修改、删除等功能,可以首先定义家族成员的数据结构,然后将每个功能写成一个函数来完成对数据的操作,最后完成主函数以验证各个函数功能并得出运行结果。一 需求分析1. 系统需求本系统是家谱管理系统,顾名思义,是用来管理家族资料的,要实现建立新家谱,查找家谱文件,增加家族成员,修改家族成员,删除家族成员和查找家族成员等基本功能。家谱管理系统是给家族长辈管理家族资料用的,对电脑的操作不一定熟悉,所以操作界面一定要友好,一定要方便,dos界面的操作一般比较枯燥,综合各种原因,要用mfc实现可视化的界面。2. 环境需求硬件:acer aspire 4740g i5处理器 2g内存 320g硬盘软件:vs 2008二 总体设计3.1 总体设计框架删除结点修改结点添加结点保存家谱读取文件建立家谱程序入口配偶信息关系查询基本查询输出家谱 图1 系统总体设计模块结构图3.2 数据结构设计 关于树形的结构:在树形结构的选择上,根据实际中多子女的现象选择一般树,考虑到家谱中成员可能存在的不定成员数问题,抛弃了以数组为基础的一般树方案,决定用链表来实现。树形结构的外存保存。为了提高效率,树形结构在程序初始化时由外存文件一次读入内存,此后不管插入还是修改,删除都不再对外存的树结构保存文件进行操作,只在内存中处理,程序退出时对外存树结构文件进行一次更新。也就是说,不管在程序运行中中对家谱结构进行多少种,多少次的操作,外存的树结构文件始终只会被程序访问两次。以二叉链表作为树的存储结构,链表中的两个链域分别指向该结点的第一个孩子结点和下一个兄弟结点,它通过描述每个结点的一个孩子和兄弟信息来反映结点之间的层次关系,其具体的结点结构为:firstchilddatanextsibling其中,firstchild为指向该结点第一个孩子的指针,nextsibling为指向该结点下一个兄弟,elem是数据元素内容,举例如下:3.3 算法设计1、家谱的创建和结点的添加 家谱采用的树的结构,通过左孩子,右兄弟的方式变为二叉树,创建的过程实际上就是二叉树的添加结点的过程,根据父亲的名字添加在父亲结点的左边。代码如下:家谱的创建familytree:familytree() t=null;/开始为空家谱 家谱结点的添加void familytree:add(person parent, person addnode) /将addnode添加到parent作为parent的孩子结点 int n=0; addnode-firstchild=addnode-nextsibling=null; /初始时firstchild同nextsibling都为空 addnode-parent=parent; if(parent=null) /如果父结点空 if(t=null) /如果根结点空 addnode-data.depth=n; t=addnode; /将addnode赋给根结点 return; n=t-data.depth+1;/否则将原来的根结点成为新根结点的孩子 t-data.depth=n; /并使原来根结点的depth值加1 addnode-firstchild=t; t-parent=addnode; t=addnode; return; strcpy(addnode-data.parentname,); n=parent-data.depth+1; addnode-data.depth=n;/将depth值加1 if(parent-firstchild=null) /如果parent无孩子,把addnode加入其firstchild parent-firstchild=addnode; else insertsibling(parent-firstchild,addnode); /否则插入到相应的兄弟结点中去 2、 家谱结点的修改家谱结点的修改就是将结点的指针传入,更新数据就可完成,代码如下:void familytree:modify(person &curnode,person newnode) /修改某个人的信息 strcpy(,); strcpy(curnode-data.birthplace,newnode-data.birthplace); strcpy(curnode-data.sex,newnode-data.sex); strcpy(curnode-data.occupation,newnode-data.occupation); strcpy(cation,cation); strcpy(curnode-data.top_headship,newnode-data.top_headship); curnode-data.height=newnode-data.height; curnode-data.birthdate=newnode-data.birthdate; curnode-data.deathdate=newnode-data.deathdate; 3、 家谱结点的删除结点的删除,如果该结点没有子节点,则直接删除该结点所有信息,如果结点有子节点,则不能删除。void ccmy_dlg:ondelete()htreeitem pnode=m_ptreepage-m_showtree.getselecteditem();if(!pnode)messagebox(请选择结点再删除!);return;if(datatree.havechild(m_curnode)messagebox(该结点有孩子结点,不能直接删除!);return;if(messagebox(确认删除?,警告,mb_iconwarning|mb_okcancel)!=1)return;datatree.deletenode(m_curnode);/删除datatree中相应的数据questionm_ptreepage-m_showtree.deleteitem(pnode);if(m_ptreepage-m_showtree.getcount()=0)/删除后若树为空getdlgitem(idc_generation)-setwindowtext(未选结点);getdlgitem(idc_linealname)-setwindowtext();getdlgitem(idc_matename)-setwindowtext();getdlgitem(idc_whosbrief)-setwindowtext(简介);getdlgitem(idc_information)-setwindowtext();bismemory=true;4、 家谱的存储和读取家谱信息的存储是按先序遍历的方式依次存入硬盘的,读取的时候,将第一个结点的信息对应根结点,后面依次根据父亲的姓名使用插入函数完成家谱的重建,代码如下:家谱的存储void familytree:savefamilytree() /保存二叉树到文件 fstream f(1.dat,ios:binary|ios:out);/以二进制写方式打开文件 if(!f) cerr文件打开失败!endl;/如果不能打开,显示出错信息 return;preordertraverse(f,t,savenode);/调用先序遍历写二叉树信息到文件f.close();/关闭文件/person& t=familytree:getroot();/ 返回家谱的根结点 /return t;家谱的重建(从文件读取)void familytree:createfamilytree() destroyfamilytree();/删除原来家谱树结构 int n=0;/初始化数组下标,用来看有几多个数据 fstream f(1.dat,ios:binary|ios:in);/以二进制读方式打开 if(!f) cerr文件打开失败!endl;/不能打开,显示出错信息 return;f.seekg(0,ios:end);/指针移到文件尾 long posend=f.tellg();f.seekg(0,ios:beg);/指针移到文件头 person parentt=new csnode;person tempmax_char_num;/ 定义读取数据的数组 for(int i=0;imax_char_num;i+)tempi=new csnode; / 初始化一个地址值,且不能为空否则出错= if(posend=f.tellg() /记录文件尾位置 f.tellg(= )/ cout这是一个空家谱!data),sizeof(info); n+; newfamilytree(); t=temp0;t-firstchild=t-nextsibling=null;/将第一个赋给根结点 t-parent = null;for(int j=1;jdata.parentname); if(parentt) tempj-firstchild=tempj-nextsibling=null; tempj-parent=parentt; if(parentt-firstchild) insertsibling(parentt-firstchild,tempj); else parentt-firstchild=tempj; f.close();/关闭文件流 5、 家谱信息的遍历主要使用递归的方式遍历家谱树,代码入下:先序遍历:void familytree:preordertraverse(fstream &f,person &t, void (_cdecl *visit)(fstream &f,person &t) /先序遍历二叉树,并执行visit函数 if(t) (*visit)(f,t); preordertraverse(f,t-firstchild,visit); preordertraverse(f,t-nextsibling,visit); 6、 家族成员的查找查找部分涉及的查找方法多样,这里用按姓名查找来代表,其他查找使用的算法思想是类似的,使用递归的方法,代码如下:void familytree:findbyname(person& t,person& tname,char* name)/search the name in info from root t /查找姓名name的人,若在家谱中,用tname返回,否则tname为空,tname初始为空 if(t) if(strcmp(t-,name)=0) /用string库的strcmp()比较两个字符串,若相等,则找到符合条件的 tname=t; else findbyname(t-firstchild,tname,name); /对t的firstchild递归搜索 findbyname(t-nextsibling,tname,name); /对t的nextsibling递归搜索 三 程序实现程序实现部分是算法设计的补充与完善,代码会与算法设计有不同,而且实现了mfc界面显示部分,最终工程的实现以程序的为主。注:代码太长不附在文档上四 测试报告1. 初始化界面: 图2 系统初始化界面效果图2文件读取保存模块 2.1 新建家谱 新建家谱实际操作为创建该家谱第一代成员,即该树的根结点。默认创建男性,默认创建当前结点的孩子结点,第一代不能创建兄弟结点,按取消操作,退出创建此家谱 图3 新建家谱界面设计效果图2.2 打开文件(1) 按打开按键,弹出文件窗口,默认打开txt格式文件图4 打开载入文件界面设计效果图(2) 打开文件后,操作窗口标题栏会显示该文件的文件名,并显示本家谱的信息 图5 打开文件信息效果图2.3 保存文件按保存按键,直接保存信息到文件,按另存为按键,弹出另存为窗口,可以选择保存路径保存家谱文件。 图6 保存文件信息页面效果图3. 操作模块3.1创建新结点 点击已经存在的一个结点,点击创建新结点按钮,表示在当前结点下创建子节点或者兄弟结点,左边显示编辑框,输入名字信息和配偶名字信息,可以选择性别,可以选择所创建新结点是当前结点的子节点或是兄弟结点。 图7 创建结点页面效果图3.2 修改结点点击要修改的结点,按修改结点按钮,左边显示编辑框,可以修改名字信息和配偶信息 图8 修改结点页面设计效果图3.3 删除结点(1) 删除子节点。选择要删除的子节点,按删除结点按钮,弹出警告窗口,询问是否确认删除结点,按确定删除结点 图9 删除子节点页面效果图(2) 删除有子节点的父节点,会弹出警告窗口,说明有子节点,不能删除该结点 图10 删除父节点页面效果图4. 查找4.1按照姓名信息关键字查找(1) 不区分大小写 图11 按照名字信息不分大小写查找页面效果图(2) 区分大小写 图12 按照姓名信息区分大小写查找页面效果图4.2 按照配偶名字信息关键字查找图13 按照配偶姓名信息查找页面效果图五 目标完成总结1. 完成了新家谱的创建,由根结点开始创建新的家谱树2. 完成了家谱文件的读取,可以打开指定路径的文件并在系统中显示该家谱信息3. 完成了家谱文件的保存,可以把新建或者修改的家谱文件保存到指定的路径4. 完成了家谱树中新结点的创建,可以创建原有结点的兄弟结点或者子结点,根节点只能创建其子结点5. 完成了家谱树中任意结点的修改功能,可以修改结点的信息和其配偶信息6. 完成了家谱树中任意子结点的删除功能,有子结点的父节点无法直接删除7. 完成了家谱树中结点的查找功能,可以按照姓名信息区分大小写或者不分大小写查找,也可以按照配偶信息查找六 遇到的问题和解决方案1. 需要设计一个简单易用的系统,方便没有计算机技术的管理人员使用,普通的dos界面就无法满足此要求了,所以就要采取编写可视化的解决方案。2. 没有学过可视化编程的相关技能,要从零开始学习此门课程,通过购买相关书籍和上网查找资料解决编程过程中遇到的问题。3. 测试阶段总会出现这样那样的问题,这时候就需要很多的耐心,并且要细心的处理每个错误。七 尚未解决的问题和应对策略1. 在删除结点功能上,只能删除子结点,不能删除拥有子结点的父结点,要解决这个尚未解决的问题,需要在程序上做修改,在树形结构上做修改。但是由于完成系统之后,还没写报告,由于时间紧迫,没有添加此项功能。2. 在删除结点功能上,每次只能删除一个结点,在效率上未能体现。这个问题是比较难解决的问题,以我现在的编程能力暂时未能想到解决方案,在日后的学习中会慢慢发掘和探索解决方法。3. 数据没有加密,容易篡改。由于数据存放于txt文件里面,修改里面的数据较为简单,严重影响系统的安全性。可以定义一种二进制文件,只有本系统才能打开,这样就对数据进行了加密。八 收获和心得这次大作业的完成时间是整整一个暑假,但回想起来,时间都用在实习上,没有好好利用暑假的两个月来做课程设计。由于我本身编程能力不强,构思,写代码,修改,调试的时间加起来绝对是要花上不少时间的,而且对于可视化mfc之前从来没用过,都要自学,所花的时间就更多了。就是因为付出很多,所以在前期的设计组织中,中期的代
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025至2030中国电开水器行业发展研究与产业战略规划分析评估报告
- 2025至2030中国生物玻璃行业产业运行态势及投资规划深度研究报告
- 2025至2030中国玄武岩纤维袖行业市场占有率及投资前景评估规划报告
- 2025至2030中国特种物流行业发展趋势分析与未来投资战略咨询研究报告
- 智慧城市公共安全监控的法律问题研究
- 企业培训中的在线教育应用与实践案例分析
- 心理引导与学生学习动力的关系研究
- 教育心理学在青少年教育中的运用
- 学生心理健康与学习成效的关联性分析
- 探索个性化教育模式下的游戏化和情感支持融合策略
- 呼伦贝尔农垦集团有限公司招聘笔试题库2025
- 2024年新人教版化学九年级上册全册课件(新版教材)
- 医院检验科实验室生物安全程序文件SOP
- 病原学检测阴性肺结核诊断流程T∕CHATA 008-2020
- 广东省大学生校外实践教学基地
- 生物质气化耦合高效发电与多联产技术20161127 (1) (1)
- 正畸头影测量分析
- 如何使用S1000D规范
- 二十四山择吉天机(全)
- 湘美版六年级下册美术第七课《标签与品牌》PPT课件
- 乳腺MRI诊断 乳腺病变的MR诊断
评论
0/150
提交评论