【数据结构课设】家谱管理系统(内附源码)

简介: 家谱管理系统是数据结构课程的一个经典的课程设计,也算是一个比较庞大的程序了吧,写出来还是蛮不容易的!分享出来希望能对大家有帮助!

前言


家谱管理系统是数据结构课程的一个经典的课程设计,也算是一个比较庞大的程序了吧,写出来还是蛮不容易的!分享出来希望能对大家有帮助!


课设题目


家谱管理系统


【问题描述】


实现具有下列功能的家谱管理系统


【功能要求】


(1)输入文件以存放最初家谱中各成员的信息,成员的信息中均应包含以下内容:姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡),也可附加其它信息、但不是必需的。

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

(3)以图形方式显示家谱。

(4)显示第n代所有人的信息。

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

(6)按照出生日期查询成员名单。

(7)输入两人姓名,确定其关系。

(8)某成员添加孩子。

(9)删除某成员(若其还有后代,则一并删除)。

(10)修改某成员信息。

(11)按出生日期对家谱中所有人排序。

(12)打开一家谱时,提示当天生日的健在成员。


【基本要求】

建立至少30个成员的数据,以较为直观的方式显示结果,并提供文稿形式以便检查。


【界面要求】

有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。


【存储结构】

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


界面展示

这里展示一小部分,其他的大家后期根据代码慢慢了解


image.png


image.png


image.png

image.png代码


实现

这个系统写起来还是比较庞大的,需要定义很多函数来慢慢实现,所以我们把所有需要用到的头文件和函数的定义都存放在我自己定义的头文件里面,这样我们使用时,只需要导入我们自己定义的头文件即可。


自定义头文件

文件名为: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多行,所以我就传到文件上来了,点击蓝色字体可以直接到下载页面。



相关文章
|
17天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
91 9
|
16天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
58 16
|
16天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
65 8
|
18天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
45 4
|
20天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
50 3
|
1月前
|
Java C++ 索引
让星星⭐月亮告诉你,LinkedList和ArrayList底层数据结构及方法源码说明
`LinkedList` 和 `ArrayList` 是 Java 中两种常见的列表实现。`LinkedList` 基于双向链表,适合频繁的插入和删除操作,但按索引访问元素效率较低。`ArrayList` 基于动态数组,支持快速随机访问,但在中间位置插入或删除元素时性能较差。两者均实现了 `List` 接口,`LinkedList` 还额外实现了 `Deque` 接口,提供了更多队列操作。
23 3
|
18天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
38 0
|
3月前
|
测试技术
【初阶数据结构篇】栈的实现(附源码)
在每一个方法的第一排都使用assert宏来判断ps是否为空(避免使用时传入空指针,后续解引用都会报错)。
39 2
|
3月前
|
测试技术
【初阶数据结构篇】队列的实现(赋源码)
首先队列和栈一样,不能进行遍历和随机访问,必须将队头出数据才能访问下一个,这样遍历求个数是不规范的。
32 0
|
3月前
|
存储 测试技术
【初阶数据结构篇】单链表的实现(附源码)
在尾插/尾删中,都需要依据链表是否为空/链表是否多于一个节点来分情况讨论,目的是避免对空指针进行解引用造成的错误。
37 0