当前位置:文档之家› (完整word版)家谱管理系统

(完整word版)家谱管理系统

洛 阳 理 工 学 院课 程 设 计 报 告课程名称 ___________________________________ 设计题目 ___________________________________ 专 业 ___________________________________ 班 级 ___________________________________ 学 号 ___________________________________ 姓 名 ___________________________________ 完成日期 ___________________________________数据结构课程设计 家谱管理系统 计算机科学与技术 B150405 B15080822 宋士龙 2016年12月30日课程设计任务书设计题目:家谱管理系统设计内容与要求:【问题描述】:实现具有下列功能的家谱管理系统1). 输入文件以存放最初家谱中各成员的信息,成员的信息中均应包含以下内容:姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡),也可附加其它信息、但不是必需的。

2). 实现数据的存盘和读盘。

3). 显示家谱。

4). 按照出生日期查询成员名单。

5). 按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。

6). 修改某成员信息。

【基本要求】:界面要求:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。

存储结构:学生自己根据系统功能要求自己设计,但是要求相关数据要存储在数据文件中。

测试数据:要求使用1、全部合法数据;2、局部非法数据。

进行程序测试,以保证程序的稳定。

测试数据及测试结果请在上交的资料中写明。

指导教师:_______________年月日课程设计评语成绩:指导教师:_______________年月日一、算法思想本程序是一个管理家谱的系统,通过这个系统可以对家族成员进行创建、显示、查找、修改、以及保存家谱和读取家谱功能。

该系统分为以下几个模块,分别是:创建家谱,显示家谱、按姓名和生日查找家庭成员、修改家谱、存盘、读盘以及退出系统。

本程序用到的存储形式为多叉树,因为家谱中每个人既有父母又有孩子,而且孩子的个数并不确定,所以用多叉树来存储最为合适。

用多叉树来存储,就用用到多叉树的递归创建及递归遍历。

因为是多叉树,所以遍历时用广度优先搜索合适。

本函数最主要的思想就是递归调用,每个子函数中都会用到递归。

定义结构体时给定指针数组的最大容量,来规定家谱中最多可以存多少人。

定义一个家族树的指针变量用来当每个子函数的参数,从而将其返回到主函数中。

以下时算法思想流程图:二、模块划分1.int main():主函数2.void CreatTree(TreeNode *Tree):创建家族树3.void OutPutAll(TreeNode *Tree):显示家谱4.void Menue(TreeNode *Tree):主菜单5.void SubMenue1(TreeNode * Tree):副菜单(修改选项菜单)6.void Change(TreeNode * Tree):修改家谱7.TreeNode * SearchTree(TreeNode *Tree,char name[],int length):按照姓名查找家谱成员8.TreeNode * SearchTree1(TreeNode *Tree,char birth[],int length):按照生日查找家谱成员9.void OutPutMessage(TreeNode * Tree,char name[],int length):输出按姓名查找到的家谱成员10.void OutPutMessage1(TreeNode * Tree,char birth[],int length):输出按生日查找到的家谱成员11.void SaveFamily(TreeNode *root):保存家谱12.void ReadFamily(TreeNode **root):读取家谱三、数据结构typedef struct TreeNode{int ChildNum; //记录这个人拥有几个儿女char Name[20];//记录这个人的姓名char birthday[20];//生日int marriage;//婚否(1表示结婚,0表示没结婚)int death;//生死(1表示活着,0表示过世)char Kind;//标示节点的种类有女G男Bchar address[100];//住址char livemassage[50];//死亡日期(如果其已经死亡)struct TreeNode *NextNode[20]; //记录这个人的儿女struct TreeNode *Parent; //记录这个节点的父节点}TreeNode,*tree;四、测试第一组数据为:爷爷,奶奶,爸爸,妈妈,我,二叔,二婶,姐姐,三叔,三婶,弟弟一共三代11个人。

其中爷爷是根节点,奶奶为爷爷的配偶,同时也是爷爷的第一个后继节点。

爸爸,二叔,三叔为爷爷的子女。

爸爸的配偶是妈妈,爸爸的子女是我。

二叔的配偶是二婶,子女是姐姐。

三叔的的配偶是三婶,三叔的的子女是弟弟。

进入程序之后,首先进行创建家谱,然后进行存盘,之后进行修改和查询等步骤。

退出程序在进入程序时,进行读盘。

之后在进行其他操作,程序完成之后退出即可。

图1 家族树第一组数据测试截图为:图2 显示家谱爷爷 爸爸 二叔 奶奶三叔 妈妈 二婶 三婶我 姐姐弟弟图3 按照姓名查找家族成员图4 存盘第二组数据为:图4 王家家族树第二组数据测试截屏为:图5 修改家族成员的信息王老王大 刘老王二 李大张二王小一王小二图6 修改某个人的具体信息图7 按照生日查找某人图8 读盘五、源程序#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef WIN32#define CLEAR system("cls")#define TipForSaveFilePosition printf("\t\t输入文件名及保存位置(eg: D:\\\\example.txt):")#define TipForReadFilePosition printf("\t\t文件名及其路径(eg: D:\\\\example.txt): ")#else#define CLEAR system("clear")#define TipForSaveFilePosition printf("\t\t输入文件名及保存位置(eg: /home/xiong/example.txt): ")#define TipForReadFilePosition printf("\t\t文件名及其路径(eg: /home/xiong/example.txt): ")#endif#define maxFileNameLen 50 //保存的文件名的最大长度int FLAG=0;int a=1;typedef struct TreeNode{int ChildNum; //记录这个人拥有几个儿女char Name[20];//记录这个人的姓名char birthday[20];//生日int marriage;//婚否(1表示结婚,0表示没结婚)int death;//生死(1表示活着,0表示过世)char Kind;//标示节点的种类有女G男Bchar address[100];//住址char livemassage[50];//死亡日期(如果其已经死亡)struct TreeNode *NextNode[20]; //记录这个人的儿女struct TreeNode *Parent; //记录这个节点的父节点}TreeNode,*tree;void CreatTree(TreeNode *Tree);void OutPutAll(TreeNode *Tree);void Menue(TreeNode *Tree);void SubMenue1(TreeNode * Tree);void SubMenue2(TreeNode *Tree);void Change(TreeNode * Tree);void AddNew(TreeNode * Tree);TreeNode * SearchTree(TreeNode *Tree,char name[],int length);TreeNode * SearchTree1(TreeNode *Tree,char birth[],int length) ;void OutPutMessage(TreeNode * Tree,char name[],int length);void OutPutMessage1(TreeNode * Tree,char birth[],int length);void SaveFamily(TreeNode *root);void ReadFamily(TreeNode **root);int main()//主函数{TreeNode *Tree;//TreeNode **Tree1;//Tree1=&(*Tree);Tree=(TreeNode *)malloc(sizeof(TreeNode));Tree->Parent =NULL;strcpy(Tree->Name,"0");Menue(Tree);return 0;}void Menue(TreeNode *Tree)//输出主菜单{/*TreeNode **Tree1;Tree1=&Tree;*/char c;char name[20];char birth[20];while(1){system("cls");printf("\t");printf("\n\n\t\t**********欢迎使用家族管理系统**********\n\n");printf("\n\t\t A:输入家谱信息建立树");printf("\n\t\t B:输出整个家谱信息");printf("\n\t\t C:按出生日期查找某人"); printf("\n\t\t D:按姓名查找某人"); printf("\n\t\t E:修改某个人的信息"); printf("\n\t\t F:存盘");printf("\n\t\t G:读盘");printf("\n\t\t H:退出整个程序\n\t"); c=getchar();switch(c){case 'A':TreeNode * NewNode;NewNode=(TreeNode *)malloc(sizeof(TreeNode));printf("\n\t请输入姓名:");scanf("%s",Tree->Name);printf("\n\t请输入性别女G男B:");getchar();scanf("%c",&(Tree->Kind));Tree->Parent=NewNode;Tree->Parent=NULL;//CreatTree(Tree); //printf("\n\t--------------家谱图已经建立成功---------------\n\n");printf("\n\n\t--------------请按Enter键继续操作--------------");getchar();break;case 'B':if(strcmp(Tree->Name,"0")==0){printf("\n\t家谱图的多叉树尚未建立请先建立树\n");getchar();break;}printf("\n\n\t整个家谱的主要信息如下:");OutPutAll(Tree);getchar();break;case 'C':if(strcmp(Tree->birthday,"0")==0){printf("\n\t家谱图的多叉树尚未建立请先建立树\n");getchar();break;}scanf("%s",birth);OutPutMessage1(SearchTree1(Tree,birth,20),birth,20);printf("\n\n\t-----*----*----*----*----*----*----*----*----*----*----\n\t");getchar();break;case 'D':if(strcmp(Tree->Name,"0")==0){printf("\n\t家谱图的多叉树尚未建立请先建立树\n");getchar();break;}printf("\n\t请输入你要查找的人的姓名:\n\t");scanf("%s",name);OutPutMessage(SearchTree(Tree,name,20),name,20);printf("\n\n\t-----*----*----*----*----*----*----*----*----*----*----\n\t");getchar();break;case 'E':if(strcmp(Tree->Name,"0")==0){printf("\n\t家谱图的多叉树尚未建立请先建立树\n");getchar();break;}Change(Tree);getchar();break;case 'F':if(strcmp(Tree->Name,"0")==0){printf("\n\t家谱图的多叉树尚未建立请先建立树\n");getchar();break;}SaveFamily(Tree);getchar();break;case 'G':/*if(strcmp(Tree->Name,"0")==0){printf("\n\t家谱图的多叉树尚未建立请先建立树\n");getchar();}*/ReadFamily(&Tree);getchar();break;case 'H':printf("\n\n\t-----------------本次服务到此结束------------------");printf("\n\t------------------欢迎下次使用---------------------");printf("\n\t----------------------谢谢-------------------------\n\n");break;case '\n':break;default:printf("\n\n\t--------对不起!你的选择不在服务范围之内!-----------");printf("\n\t-----------请您再次选择所需的服务项!---------------");printf("\n\t------------------谢谢------------------------\n\t");getchar();break;}if (c=='H'||c=='f')break;getchar();}}void CreatTree(TreeNode *Node) //创建树{int i;TreeNode *NewNode;NewNode=(TreeNode *)malloc(sizeof(TreeNode));Node->NextNode[0]=NewNode;Node->NextNode[0]=NULL;printf("\n\t请输入出生日期:");scanf("%s",Node->birthday);printf("\n\t请输入家庭住址:");getchar();scanf("%s",Node->address);printf("\n\t请输入是否建在(1-是或0-否):");scanf("%d",&(Node->death));if(Node->death==0){printf("\n\t请输入去世日期:");scanf("%s",Node->livemassage);}else if(Node->death=='1')printf("\n\t仍然建在");scanf("%s",NewNode->Name);if(strcmp(NewNode->Name,"0")!=0){printf("\t请输入配偶的出生日期:");scanf("%s",NewNode->birthday);printf("\n\t请输入家庭住址:");getchar();scanf("%s",NewNode->address);printf("\n\t请输入是否建在(1-是或0-否):");scanf("%d",&(NewNode->death));if(NewNode->death==0){printf("\n\t请输入去世日期:");scanf("%s",NewNode->livemassage);}else if(NewNode->death=='1')printf("\n\t仍然建在");}printf("\n\t请输入%s的子女的数目(当子女输入0时便停止输入该成员有关信息):",Node->Name);scanf("%d",&(Node->ChildNum));if((Node->ChildNum)==0&&strcmp(NewNode->Name,"0")==0)return ;if(Node->Kind=='G'||Node->Kind=='g')NewNode->Kind='B';elseNewNode->Kind='G';NewNode->ChildNum=0;NewNode->NextNode[0]=NULL;Node->NextNode[0]=NewNode;Node->NextNode[0]->Parent=Node;//孩子的父母for(i=1;i<=Node->ChildNum;i++){NewNode=(TreeNode *)malloc(sizeof(TreeNode));a++;printf("\n\t请输入%s的第%d子女的名字:",Node->Name,i);scanf("%s",NewNode->Name);printf("\n\t请输入%s的第%d子女的性别女G男B:",Node->Name,i);getchar();scanf("%c",&NewNode->Kind);NewNode->ChildNum=-1;NewNode->Parent=Node;Node->NextNode[i]=NewNode;CreatTree(Node->NextNode[i]); //从子女的数目开始}}void OutPutAll(TreeNode *Tree)int i, flag=0;printf("\n\t---****---***---***---***---***---***---***---***---***---");printf("\n\t姓名:%s 出生日期:%s 家庭住址:%s 性别: %c",Tree->Name,Tree->birthday,Tree->address,Tree->Kind);if (Tree->Kind=='G'||Tree->Kind=='g'){flag=1;printf("女");}elseprintf("男");printf("\t是否健在(1-健在,0-去世):");if(Tree->death==1) printf("1");else if(Tree->death==0) printf("0");if (!(Tree->NextNode[0])){printf("\n\t至今没有配偶和子女\n");return;}if(flag==1)printf("\n\t丈夫姓名:%s",Tree->NextNode[0]->Name);elseprintf("\n\t妻子姓名:%s",Tree->NextNode[0]->Name);printf("\t是否健在(1-健在,0-去世):");if(Tree->death==1) printf("1");else if(Tree->death==0) printf("0");for(i=1;i<=Tree->ChildNum;i++){printf("\n\t第%d个子女的姓名:%s 出生日期:%s 家庭住址:%s 性别%c",i,Tree->NextNode[i]->Name,Tree->NextNode[i]->birthday,Tree->NextNode[i]->address,Tre e->NextNode[i]->Kind);if (Tree->NextNode[i]->Kind=='G'||Tree->NextNode[i]->Kind=='g')printf("女");elseprintf("男");printf("\t是否健在(1-健在,0-去世):");if(Tree->death==1) printf("1");else if(Tree->death==0) printf("0");}printf("\n\t");for(i=1;i<=Tree->ChildNum;i++){OutPutAll(Tree->NextNode[i]);}TreeNode * SearchTree(TreeNode *Tree,char name[],int length){int i;TreeNode *NewNode;if(strcmp(Tree->Name,name)==0){if(length==0)FLAG=1;elseFLAG=0;return Tree;}if(Tree->NextNode[0]==NULL)return NULL;for(i=0;i<=Tree->ChildNum;i++){if (i==0)NewNode=SearchTree(Tree->NextNode[i],name,0);elseNewNode=SearchTree(Tree->NextNode[i],name,20);if (NewNode!=NULL)return NewNode;}return NULL;}void OutPutMessage(TreeNode * Tree,char name[],int length){int flag=0,i;TreeNode *NewNode;printf("\n\n\t-----*----*----*----*----*----*----*----*----*----*----");if(Tree==NULL){printf("\n\n\t****该家谱图中没有%s这个人的信息请确认是否输入错误*****\n",name);return;}printf("\n\n\t您所要找的人已经找到信息如下所示:");printf("\n\n\t姓名:%s出生日期:%s 家庭住址:%s 性别:%c",name,Tree->birthday,Tree->address,Tree->Kind);if (Tree->Kind=='G'||Tree->Kind=='g'){flag=1; //标记他(她)的性别}elseprintf("男");printf("\t是否健在(1-健在,0-去世):");if(Tree->death==1) printf("1");else if(Tree->death==0) printf("0");NewNode=Tree->Parent;if (FLAG==1){if(flag==1){printf("\n\n\t她是嫁入此家族的所以亲生父母信息不在家谱内包括");printf("\n\t丈夫姓名:%s",NewNode->Name);}else{printf("\n\n\t他是入赘此家族的所以亲生父母信息不在家谱内包括");printf("\n\t妻子姓名:%s",NewNode->Name);}if ((NewNode->ChildNum)>0) //判断他(她)是否有孩子{printf("\n\t的孩子的信息如下:"); //输出他(她)的孩子的信息for(i=1;i<=NewNode->ChildNum;i++){printf("\n\t姓名:%s 性别:",NewNode->NextNode[i]->Name);if (NewNode->NextNode[i]->Kind=='G'||NewNode->Kind=='g')printf("女");elseprintf("男");printf("\t是否健在(1-健在,0-去世):");if(Tree->death==1) printf("1");else if(Tree->death==0) printf("0");}}return;}if(NewNode==NULL)//判断它是不是根节点如果是的话就没有父母兄弟信息printf("\n\t是这个家谱图里最年长的人",name);else{if (NewNode->Kind=='G'||NewNode->Kind=='g') //判断父亲节点是父亲还是母亲{printf("\n\t父亲姓名:%s",NewNode->NextNode[0]->Name);}else{printf("\n\t母亲姓名:%s",NewNode->NextNode[0]->Name);printf("\n\t父亲姓名:%s",NewNode->Name);}if(Tree->NextNode[0]!=NULL) //判断他(她)是否有配偶{if(flag==1)//输出他(她)的配偶的信息printf("\n\t丈夫姓名:%s",Tree->NextNode[0]->Name);elseprintf("\n\t妻子姓名:%s",Tree->NextNode[0]->Name);if (Tree->ChildNum>0) //判断他(她)是否有孩子{printf("\n\t的孩子的信息如下:"); //输出他(她)的孩子的信息for(i=1;i<=Tree->ChildNum;i++){printf("\n\t姓名:%s 性别:",Tree->NextNode[i]->Name);if (Tree->NextNode[i]->Kind=='G'||Tree->Kind=='g')printf("女");elseprintf("男");printf("\t是否健在(1-健在,0-去世):");if(Tree->death==1) printf("1");else if(Tree->death==0) printf("0");}}elseprintf("\n\t%s至今还没有孩子",name);}elseprintf("\n\t%s至今还没有配偶和孩子\n",Tree->Name);}}TreeNode * SearchTree1(TreeNode *Tree,char birth[],int length){int i;TreeNode *NewNode;if(strcmp(Tree->birthday,birth)==0)if(length==0)FLAG=1;elseFLAG=0;return Tree;}if(Tree->NextNode[0]==NULL)return NULL;for(i=0;i<=Tree->ChildNum;i++){if (i==0)NewNode=SearchTree1(Tree->NextNode[i],birth,0);elseNewNode=SearchTree1(Tree->NextNode[i],birth,20);if (NewNode!=NULL)return NewNode;}return NULL;}void OutPutMessage1(TreeNode * Tree,char birth[],int length){int flag=0,i;TreeNode *NewNode;printf("\n\n\t-----*----*----*----*----*----*----*----*----*----*----");if(Tree==NULL){printf("\n\n\t****该家谱图中没有出生日期为%s这个人的信息请确认是否输入错误*****\n",birth);return;}printf("\n\n\t您所要找的人已经找到信息如下所示:");printf("\n\n\t姓名:%s出生日期:%s 家庭住址:%s 性别:%c",Tree->Name,Tree->birthday,Tree->address,Tree->Kind);if (Tree->Kind=='G'||Tree->Kind=='g'){flag=1; //标记他(她)的性别printf("女");}elseprintf("男");}void Change(TreeNode * Tree) //修改某个人的信息{TreeNode * NewNode;printf("\n\t请输入你要修改的人的姓名:\n\t");scanf("%s",name);NewNode=SearchTree(Tree,name,20);if(NewNode==NULL){printf("\n\n\t****该家谱图中没有%s这个人的信息请确认是否输入错误*****\n",name);return;}else{SubMenue1(NewNode);}}void SubMenue1(TreeNode * Tree) //输出副菜单{char c;int flag,i;char name[20];char birth[20];char address1[50];char Parent[2][20];TreeNode * NewNode;getchar();while(1){system("cls");printf("\t");printf("\n\n\t ---*****---请选择你的操作---****--- ");printf("\n\t---*---*---*---A:修改个人的信息---*---*---*---*---*---*---- ");printf("\n\t---*---*---*---B:修改父母的信息---*---*---*---*---*---*---- ");printf("\n\t---*---*---*---C:修改子女的信息---*---*---*---*---*---*---- ");printf("\n\t---*---*---*---D:退出-*---*---*---*---*---*---*---*---*----\n\t");c=getchar();switch(c){case 'A':printf("\n\n\t请输入修改的姓名:如果不需要修改就输入‘0’然后按Enter键继续\n\t");scanf("%s",name);if(strcmp(name,"0")!=0)strcpy(Tree->Name,name);继续\n\t");scanf("%d",&flag);if (flag==1){if(Tree->Kind=='G'||Tree->Kind=='g')Tree->Kind='B';else Tree->Kind='G';}printf("\n\n\t请输入修改的出生日期:如果不需要修改就输入‘0’然后按Enter键继续\n\t");scanf("%s",birth);if(strcmp(birth,"0")!=0)strcpy(Tree->birthday,birth);printf("\n\n\t请输入修改的家庭地址:如果不需要修改就输入‘0’然后按Enter键继续\n\t");scanf("%s",address1);if(strcmp(address1,"0")!=0)strcpy(Tree->address,address1);printf("\n\n\t个人信息修改成功");break;case 'B':if(Tree->Parent==NULL) //判断是不是头节点{printf("\n\t是这个家谱图里最顶端的人没有父母信息!",name);break;}if (FLAG==1) //判断是不是入赘或加入此间的{if(Tree->Kind=='G'||Tree->Kind=='g'){printf("\n\n\t她是嫁入此间的所以父母信息不在家谱内包括");}else{printf("\n\n\t他是入赘此间的所以父母信息不在家谱内包括");}break;}if(Tree->Parent->Kind=='G'||Tree->Parent->Kind=='g'){strcpy(Parent[0],"母亲");strcpy(Parent[1],"父亲");}else{strcpy(Parent[0],"父亲");strcpy(Parent[1],"母亲");}printf("\n\n\t请输入%s要修改的姓名:如果不需要修改就输入‘0’然后按Enter键继续\n\t",Parent[0]);scanf("%s",name);if(strcmp(name,"0")!=0)strcpy(Tree->Parent->Name,name);printf("\n\n\t请输入%s要修改的姓名:如果不需要修改就输入‘0’然后按Enter键继续\n\t",Parent[1]);scanf("%s",name);if(strcmp(name,"0")!=0)strcpy(Tree->Parent->NextNode[0]->Name,name);printf("\n\n\t-------------父母的信息修改成功----------------");break;case 'C':if(Tree->ChildNum==0){printf("\n\n\t至今还没有子女");break;}if (Tree->Parent !=NULL)if (strcmp(Tree->Name,Tree->Parent->NextNode[0]->Name)==0)//如果他是入赘或者是嫁入的就需用配偶节点完成修改{Tree=Tree->Parent;}for(i=1;i<=Tree->ChildNum;i++){printf("\n\n\t请输入%s修改的姓名:如果不需要修改就输入‘0’然后按Enter键继续\n\t",Tree->NextNode[i]->Name);scanf("%s",name);if(strcmp(name,"0")!=0)strcpy(Tree->NextNode[i]->Name,name);printf("\n\n\t是否要修改性别:如果需要就输入'1'不需要修改就输入'0'然后按Enter键继续\n\t");scanf("%d",&flag);if (flag==1){if(Tree->NextNode[i]->Kind=='G'||Tree->NextNode[i]->Kind=='g')Tree->NextNode[i]->Kind='B';else Tree->NextNode[i]->Kind='G';}}printf("\n\n\t---------------子女的信息修改成功----------------");break;case 'D':printf("\n\n\t----------------本项服务到此结束-----------------");break;case '\n':break;default:printf("\n\n\t--------对不起!你的选择不在服务范围之内!---------");printf("\n\t-----------请您再次选择所需的服务项!-------------");printf("\n\t------------------谢谢合作!----------------------\n\t");break;}if (c=='D'||c=='d')break;printf("\n\n\t--------------请按Enter键继续操作--------------");getchar();getchar();}}void SaveFamily(TreeNode *root)//保存家谱至指定文件{char saveFileName[maxFileNameLen];FILE* fp;TreeNode *queue[50], *head;int i, front, rear;//队列的头指针,尾指针printf(" ***** 保存家谱*****\n\n");//if(root==NULL)if(root == NULL){printf("\t\t家谱中无成员,无法保存!\n");return;}TipForSaveFilePosition;//文件及其绝对路径格式scanf("%s", saveFileName);getchar();fp = fopen(saveFileName, "w");//不存在则新建。

相关主题