前言
家谱管理系统是数据结构课程的一个经典的课程设计,也算是一个比较庞大的程序了吧,写出来还是蛮不容易的!分享出来希望能对大家有帮助!
课设题目
家谱管理系统
【问题描述】
实现具有下列功能的家谱管理系统
【功能要求】
(1)输入文件以存放最初家谱中各成员的信息,成员的信息中均应包含以下内容:姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡),也可附加其它信息、但不是必需的。
(2)实现数据的存盘和读盘。
(3)以图形方式显示家谱。
(4)显示第n代所有人的信息。
(5)按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。
(6)按照出生日期查询成员名单。
(7)输入两人姓名,确定其关系。
(8)某成员添加孩子。
(9)删除某成员(若其还有后代,则一并删除)。
(10)修改某成员信息。
(11)按出生日期对家谱中所有人排序。
(12)打开一家谱时,提示当天生日的健在成员。
【基本要求】
建立至少30个成员的数据,以较为直观的方式显示结果,并提供文稿形式以便检查。
【界面要求】
有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。
【存储结构】
学生自己根据系统功能要求自己设计,但是要求相关数据要存储在数据文件中。
界面展示
这里展示一小部分,其他的大家后期根据代码慢慢了解
代码
实现
这个系统写起来还是比较庞大的,需要定义很多函数来慢慢实现,所以我们把所有需要用到的头文件和函数的定义都存放在我自己定义的头文件里面,这样我们使用时,只需要导入我们自己定义的头文件即可。
自定义头文件
文件名为:Head_total.h
#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #define len 30
//日期-年月日 struct Date { int year; int month; int day; }; struct Info { int children_count;//孩子数-hzshu int alive; int alive_day;//活了多少日-ri int marry;//婚否-jiehun char name[20];//姓名 char birth_place[20];//出生地点 -birthplace[20] Date birth_date;//结构date定义的出生日期 Date death_date;//结构date定义的死亡日期 int sex;//性别 char wife_or_husband[20];//配偶 char address[50];//家庭住址 char resume[100];//简历 //其他信息如下 int height;//高度 char occupation[20];//职业 char education[20];//受教育程度 char parent_name[20];//父亲姓名,用于添加节点时用 int Depth;//二叉树深度,输出二叉树时用 };
typedef struct CSNode { Info data; //个人信息类型结构 CSNode *first_child,*next_brother,*parent; //csnode的第一个孩子节点,下一个兄弟节点,双亲节点 }*person; //定义链式队列结点 typedef person QElemType; typedef struct QNode { QElemType data; struct QNode *next; }QNode,*QueuePtr; typedef struct { QueuePtr front,rear; }LinkQueue;
//函数声明 void start_up(person &T);//给结点置空 void main_menu(person &);//主菜单 int Create_familytree(person &,person &);//创建家谱树 person find_name(person &,char Name[]);//按姓名查找指定成员函数 int birth_date(person &);//输入出生日期 int death_date(person &); //输入死者死亡日期 int judge_birth_date(person &); //判断出生日期是否在今天之前 int judge_death_date(person &); //判断死亡日期死亡日期是否正确 void survival_day_sum(int &,int &,int &,int &,int &,int &);//计算生存天数 void level(person &); //计算每位家族成员的辈分 void level_every(person &);//计算一位家族成员的辈分 void sort(person &); //排序 void sort_every(person &);//为一个父亲的孩子按出生日期排序 void add_new_member(person &);//添加成员函数 void preserve(person &);//保存成员信息函数 void preserve_member(person &,FILE *);//保存一个成员信息函数 void preserve_family(person &,FILE *); //保存所有成员信息函数 int DeQueue(LinkQueue &,QElemType &);//出队列操作 void InitQueue(LinkQueue &);//构造一个空队列 int QueueEmpty(LinkQueue );//判断链式队列是否为空 void EnQueue(LinkQueue &,QElemType ); //进队列操作 void start_correct(person &);//该函数的作用是每次从打开家谱,都会根据现在的时间重新计算活着的成员的寿命 void show(person &); //显示家谱树函数 void read_node(person &,FILE *);//从文件中读取所有成员节点 void read_node_every(person &,FILE *); //从文件中读取一个成员节点 void show_tree_member(person &);//每一个具体展现 void show_tree(person &);//把家谱成员姓名通过一个层次化的家谱树显示出来 void lookup(person &);//通过名字查找相应的成员,并显示其信息 void show_member(person &); //显示一个成员所有信息的函数 void Delete(person &);//采用后续遍历的方法删除成员节点 void find(person &); //通过关键字搜索家谱成员 int kmp(char str[], char ptrn[]); //KMP算法,用于搜索简历内容 void member_message_num(person &); //统计家谱成员信息函数 void relation(person &); void QuickSort(person e[], int , int ); //快速排序算法,用于寿命排序
主函数
准备工作结束之后,接下来看看主函数
主函数就是产生一个空结点,用于家族谱的判空操作,然后进入这个系统的主界面
#include "Head_total.h" void main() //主函数 { person T; T=(person)malloc(sizeof(CSNode)); start_up(T); strcpy(T->data.name,"0"); //首先设置第一个节点的成员姓名为0,用于家族谱的判空操作 main_menu(T); return; } void start_up(person &T) //初始化,把指针置为空 { T->parent=NULL; T->first_child=NULL; T->next_brother=NULL; return; }
菜单界面
接下来看看这个系统的主界面
它主要通过while循环与switch来实现功能,并且通过 SetConsoleTextAttribute()函数来控制控制台窗口字体颜色和背景色,使界面更加优美
原谅我调不出好看的颜色。。
#include "Head_total.h" void main_menu(person &T) //主菜单程序 { int j=1; char i; while (j) { system("cls"); //清屏 HANDLE consolehwnd; consolehwnd = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(consolehwnd,FOREGROUND_INTENSITY|FOREGROUND_GREEN); //设置屏幕字体颜色 printf("\t"); printf("\n\n\t *******家谱管理系统课设版1.0******* "); SetConsoleTextAttribute(consolehwnd,FOREGROUND_INTENSITY | FOREGROUND_BLUE); printf("\n\t\t---------------------------------------------\n\t"); SetConsoleTextAttribute(consolehwnd,FOREGROUND_INTENSITY |FOREGROUND_GREEN | FOREGROUND_BLUE); //printf("\t\t 家谱管理系统\n\t"); printf("\t\t 0. 退出系统 \n\t"); printf("\t\t 1. 新创建家谱树 \t\n\t"); printf("\t\t 2. 添加家谱成员 \t\n\t"); printf("\t\t 3. 保存家谱信息到文件 \t\n\t"); printf("\t\t 4. 从文件读取显示家谱 \t\n\t"); printf("\t\t 5. 按姓名查找家谱成员 \t\n\t"); printf("\t\t 6. 按关键字查找家谱成员 \t\n\t"); printf("\t\t 7. 统计家谱成员 \t\n\t"); printf("\t\t 8. 通过名字确定两人关系 \t\n\t"); SetConsoleTextAttribute(consolehwnd,FOREGROUND_INTENSITY | FOREGROUND_BLUE); printf("\t---------------------------------------------\n\t"); printf("\t请输入你的操作(0~8):\n"); i=getchar(); fflush(stdin);//刷新缓冲区,将缓冲区内的数据清空并丢弃 switch(i) { case '0': j=0; break; case '1': system("cls"); //清屏 if(strcmp(T->data.name,"0")==0) { printf("下面请输入祖先的信息\n"); person b; b=(person)malloc(sizeof(CSNode)); start_up(b); if(Create_familytree(b,T)) { T=b; level(T); sort(T); printf("\n\t ***** 家谱树已建立完成 ***** \n\t"); } } else printf("家谱树已存在,要新建家谱树请先删除原有家谱树!\n"); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); //程序运行到此处会暂停,等待键盘命令 break; case '2': system("cls"); //清屏 add_new_member(T); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); break; case '3': system("cls"); //清屏 if(strcmp(T->data.name,"0")) preserve(T); else printf("家谱树为空,无法保存!\n"); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); break; case '4': system("cls"); //清屏 show(T); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); break; case '5': system("cls"); //清屏 lookup(T); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); break; case '6': system("cls"); //清屏 find(T); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); break; case '7': system("cls"); //清屏 member_message_num(T); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); break; case '8': system("cls"); //清屏 relation(T); fflush(stdin); printf("\n即将返回主菜单!\n"); system("pause"); break; default: printf("你的操作有误,请重新选择!\n"); fflush(stdin); system("pause"); } } return; }
结语
因为代码行数太多了,大概用2000多行,所以我就传到文件上来了,点击蓝色字体可以直接到下载页面。