资源描述
洛 阳 理 工 学 院
课 程 设 计 报 告
数据结构课程设计
课程名称 ___________________________________
家谱管理系统
设计题目 ___________________________________
计算机科学和技术
专 业 ___________________________________
B150405
班 级 ___________________________________
B15080822
学 号 ___________________________________
宋士龙
姓 名 ___________________________________
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男B
char 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男B
char 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;
}
printf("\n\t请输入你要查找出生日期:");
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();
break;
}*/
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仍然建在");
printf("\n\t请输入%s配偶姓名(输入0代表没结婚):",Node->Name);
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';
else
NewNode->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("女");
}
else
printf("男");
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);
else
printf("\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,Tree->NextNode[i]->Kind);
if (Tree->NextNode[i]->Kind=='G'||Tree->NextNode[i]->Kind=='g')
printf("女");
else
printf("男");
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;
else
FLAG=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);
else
NewNode=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; //标识她(她)性别
printf("女");
}
else
printf("男");
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("女");
else
printf("男");
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->Name);//输出她(她)父母亲信息
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);
else
printf("\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("女");
else
printf("男");
printf("\t是否健在(1-健在,0-逝世):");
if(Tree->death==1) printf("1");
else if(Tree->death==0) printf("0");
}
}
else
printf("\n\t%s至今还没有孩子",name);
}
else
printf("\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;
else
展开阅读全文