基于角色管理的简易家谱管理系统(C++/C(几乎都是C))2020-06-16

一、课题内容和要求
(一)课题要求
家谱管理系统是查询家谱信息必不可少的一部分,利用家谱管理系统可以清楚的了解家族成员信息。该家谱管理系统是通过树来实现的。要求系统界面友好,易于操作。
(二)课题要求
a)需要设置普通用户、超级管理员不同角色,不同角色登录后的权限各不相同,普通用户可以进行查询;超级管理员有对所有成员增加、删除和修改的权限。
b)家谱中的成员的信息均应包括姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡)等,也可附加其他信息,并且存储与文本文件中。
c)查询功能。可按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息、所在辈分);按照出生日期查询成员名单。
d)按照出生日期对家谱中所有人进行排序
e)打开家谱时,提示当天生日的健在成员
f)以图形方式显示家谱
(三)其他要求
(1)变量、函数命名符合规范
(2)注释详细:每个变量都要求有注释说明用途:函数有注释说明功能,对参数、返回值也要以注释的形式说明用途;关键语句段要求有注释解释
(3)程序的层次清晰,可读性强。
(4)界面美观,交互方便。
头文件treeheader.h

#ifndef TREECO_H_
#define TREECO_H_
#include <iostream>
#include <stdio.h>
#include <fstream>
#include <time.h>  //获取搜索时刻的时间 
#include <stdbool.h>        //布尔类型
#include <stdlib.h>  //动态分配内存
#include <string.h>  //字符串处理
#include <memory.h>

#define MAX_TREE_SIZE 20  //最大父亲数量
#define LEN 20      //基本属性的长度    
#define ERROR 0  
#define OK 1
using namespace std;
typedef int Status; // 状态
typedef struct //个人信息结构体
{
    char name[LEN];  //姓名
    char bothDay[LEN]; //出生日期
    int getMatings;    //是否结婚
    char address[LEN];  //其住址
    int keepAlive;     //是否健在
    char deathDay[LEN]; //若死亡,死亡日期
}ElemType;
typedef struct CTNode  //孩子节点
{
    int child;   //自身的标记,数组下标
    struct CTNode *next;  //指针域
}ChildPtr;

typedef struct   //表头结构
{
    int parent;  //父母的信息,数组下标
    ElemType data; //个人信息
    ChildPtr* firstchild;   //
}CTBox;

typedef struct  //树结构
{
    CTBox nodes[MAX_TREE_SIZE];   //节点数组
    int r, n;                       //根的位置和节点数
}CTree;
void User_login(CTree *tree);   //用户账户密码管理
void main_menu_super(CTree *tree);  //管理员菜单
void main_menu_normal(CTree *tree);  //普通用户菜单
char get_choice_menu_super();  //超级用户菜单的选择
char get_choice_menu_normal();//普通用户菜单的选择
char get_choice_Inquire();  //查询系统的选择
char get_choice_Modify();  //修改菜单的选择
ElemType Input();//录入成员信息函数
void Init(CTree *tree);  //初始化家族谱
void show_seniority(CTree *tree, int flag);  //显示查询此人时候的辈分
Status Exist_Name(CTree *tree);  //以姓名查询是否存在此人
Status Exist_BothDay(CTree *tree);  //以出生日期判断是否存在此人
void Inquire(CTree *tree); //查询功能
void Add_Child(CTree *tree, int i);  //为数组节点增加孩子 
void Add_Parent_Init(CTree *tree, int i); //为数组节点确定父节点 
void Add_Parent_Person(CTree *tree, int i);//增加新成员时父亲节点的动态变化
Status Add_Person(CTree *tree);//增加新成员
Status Remove(CTree *tree);  //删除某人
Status Modify(CTree *tree);  //修改某人信息
Status Sort_BothDay(CTree *tree);  //对家谱里的人按照出生日期进行排序
void Destroy(CTree *tree);
void Data_write(CTree *tree);
#endif

头文件中函数实现文件:implements.cpp

#include "treeheader.h"
void User_login(CTree *tree)
{
    char passpord[LEN] = {"123123"};    //超级用户的密码
    char normalUser[LEN] = {"user_normal"};  //普通用户的账号
    char superUser[LEN] = {"user_super"}; //超级用户的账号
    char input_user[LEN];  //接收用户名输入
    char input_password[LEN]; //接收超级用户的密码输入
    printf("***********\t欢迎登陆家族管理系统\t***********\n");
    printf("输入您的用户名:");
    gets(input_user);
    if(!strcmp(input_user, normalUser))  // 判断此输入是否与普通用户名相同
    {
        main_menu_normal(tree);  //显示普通用户的菜单
    }
    else if(!strcmp(input_user, superUser))  //判断此输入是否与超级用户名相同
    {
        printf("请输入管理员密码:");
        gets(input_password);  //接收密码输入
        if(!strcmp(input_password,passpord))  // 判断密码是否正确
        {
            main_menu_super(tree);  //显示超级用户的菜单
        }
        else
        {
            printf("密码输入错误!程序终止!!\n");
            exit(-1);  //密码错误,退出程序
        }
    }
}

void main_menu_super(CTree *tree)  //超级用户的菜单
{
    int status;  //判断选择后执行的成功与否
    int choice;  //根据选择而执行相关功能
    while((choice = get_choice_menu_super()) != 'q')
    {
        switch (choice)
        {
        case 'a':
            Init(tree);  //调用初始化函数
            break;
        case 'b':
            Inquire(tree);  //调用查询功能
            break;
        case 'c':
            status = Add_Person(tree);  //调用增加成员函数,如果成功添加,则返回OK,反之,返回ERROR
            if(status)
            {
                printf("添加新成员成功!\n");
            }
            break;
        case 'd':
            status = Remove(tree);  //调用删除成员函数,如果成功删除,则返回OK,反之,返回ERROR
            if(status)
            {
                printf("删除此人操作成功!\n");
            }
            else
            {
                printf("家谱中没有不存在此人!\n");
            }
            break;
        case 'e':
            status = Modify(tree);   //调用修改成员函数,如果成功修改,则返回OK,反之,返回ERROR
            if(status)
            {
                printf("修改此人操作成功!\n");
            }
            else
            {
                printf("家谱中没有不存在此人!\n");
            }
            break;
        case 'f':
            status = Sort_BothDay(tree);  //调用按照生日排序成员函数,如果成功排序,则返回OK,反之,返回ERROR
            if(status)
            {
                printf("排序操作成功!\n");
            }
            else
            {
                printf("排序操作失败!\n");
            }
            break;
        case 'g':
            Destroy(tree);
            break;
        case 'h':
            Data_write(tree);
        case 'q':
        default:
            break;
        }
    }
}

void main_menu_normal(CTree *tree)
{
    int status; //判断选择后执行的成功与否
    int choice;//根据选择而执行相关功能
    while((choice = get_choice_menu_normal()) != 'q')
    {
        switch (choice)
        {
        case 'a':
            Init(tree); //调用初始化函数
            break;
        case 'b':
            Inquire(tree); //调用查询功能
            break;
        case 'c':
            status = Sort_BothDay(tree); //调用按照生日排序成员函数,如果成功排序,则返回OK,反之,返回ERROR
            if(status)
            {
                printf("排序操作成功!\n");
            }
            else
            {
                printf("排序操作失败!\n");
            }
            break;
        case 'q':
        default:
            break;
        }
    }
}

char get_choice_menu_super()
{
    int ch;  //定义接收输入的变量
    printf("\t\t欢迎使用此家族管理系统!!!\t\t\t\n");
    printf("*************************************\n");
    printf("Enter the letter of your choice:\n");
    printf("a.  初始化家族谱\t\tb.  查询信息\n");
    printf("c.  增加新成员  \t\td.  删除成员\n");
    printf("e.  修改成员    \t\tf.  按生日进行排序\n");
    printf("g.  释放内存    \t\th.  存入文本文件\n");

    printf("**************q.    退出程序***********\n");
    ch = getchar(); //接收输入
    while(getchar() != '\n')   //清空缓冲区
    {
        continue;
    }
    return ch;  //返回输入选项,启动相关函数调用
}

char get_choice_menu_normal()
{
    int ch; //定义接收输入的变量
    printf("\t\t欢迎使用此家族管理系统!!!\t\t\t\n");
    printf("*************************************\n");
    printf("Enter the letter of your choice:\n");
    printf("a.  初始化家族谱\t\tb.  查询信息\n");
    printf("c.  按生日进行排序\t\tq.    退出程序\n");
    printf("************************************\n");
    ch = getchar(); //接收输入
    while(getchar() != '\n')//清空缓冲区
    {
        continue;
    }
    return ch;     //返回输入选项,启动相关函数调用
}

char get_choice_Inquire()
{
    int ch;//定义接收输入的变量
    printf("欢迎使用此家族管理系统的查询系统!!!\n");
    printf("a.  根据姓名查询                     b.  根据生日查询\n");
    ch = getchar();//接收输入
    while(getchar() != '\n')//清空缓冲区
    {
        continue;
    }
    return ch;//返回输入选项,启动相关函数调用
}

char get_choice_Modify()
{
    int ch;//定义接收输入的变量
    printf("欢迎使用此家族管理系统的修改系统!!!\n");
    printf("a.  编辑姓名                     b.  编辑出生日期\n");
    printf("c.  编辑是否健在                  d.  编辑是否已婚\n");
    ch = getchar();//接收输入
    while(getchar() != '\n')//清空缓冲区
    {
        continue;
    }
    return ch;//返回输入选项,启动相关函数调用
}

ElemType Input()
{
    ElemType p;  //定义个结构体变量,用于初始化调用此函数时的成员信息
    printf("成员姓名:");
    gets(p.name);  //接收姓名
    printf("出生日期:");
    gets(p.bothDay);  //接收出生日期
    printf("成员住址:");
    gets(p.address);  //接收住址
    printf("是否结婚(0/1):");  //0代表未婚,1代表已婚
    scanf("%d",&p.getMatings);  //接收是否结婚
    getchar();
    printf("是否健在(0/1):");//0代表死亡,1代表健在
    scanf("%d",&p.keepAlive);  //接收是否健在 
    getchar();
    if(p.keepAlive == 0)   //若死亡,接收死亡日期
    {
        printf("死亡日期:");
        gets(p.deathDay);  
    }
    return p;  //返回结构体变量,初始化此成员的基本个人信息
}

void Init(CTree *tree)  //初始化
{
    printf("请确定初始化家谱信息需要的成员数量:");
    scanf("%d",&tree->n);  //接收初始化的时候的成员数
    printf("请依次输入各个人的信息:\n\n");
    tree->r = 0;    //根结点在数组中的位置!!!
    for(int i=0; i<tree->n; i++)   //循环完善每个成员的信息,包括其孩子和父亲
    {
        printf("***********\t正在完善第%d个成员的信息:\t***********\n",i+1);
        // printf("正在完善第%d个人的信息:\n",i+1);
        fflush(stdin);  //刷新缓冲区
        tree->nodes[i].data = Input();  //调用Input()函数,初始化此成员信息  
        tree->nodes[i].firstchild = NULL;  //初始化此成员的孩子域为NULL
        tree->nodes[i].parent = -1;  //初始化此成员的父亲在数组中的位置为-1,即为祖先
        Add_Child(tree, i);  //调用初始化此成员的孩子信息
        Add_Parent_Init(tree, i); //调用函数初始化此成员的父亲信息
        printf("**********************************************\n");
    }
}

void show_seniority(CTree *tree, int label)  //label为此人在数组中的位置
{
    int book[MAX_TREE_SIZE] = {0};  //存入数组中每个成员的辈分
    int flag;  //标记成员的父亲在数组中的下标
    int cnt = 0;  //根据cnt的值得出此成员的辈分
    for (int i = 0; i < tree->n; i++)   //用迭代替代递归实现,遍历树形结构的家谱普
    {
        flag = tree->nodes[i].parent;   
        while(flag != -1)  //如果还没有到祖先节点,接继续执行循环体
        {
            flag = tree->nodes[flag].parent;
            cnt++;
        }
        book[i] = cnt+1;  //第i个成员的辈分
        cnt = 0; 
    }
    printf("此人所在辈分是:%d\n",book[label]);
}

Status Exist_Name(CTree *tree)  //以姓名查询是否存在此人
{
    int cnt = 0;  //统计此人孩子的个数
    int flag;   //得到这个人的此时此刻查询的孩子在数组的下标
    char demo[LEN];  //接收需要查询人的姓名
    printf("输入你要找的人的名字:");
    gets(demo); 
    ChildPtr * p = NULL;  //输出其孩子信息
    int book[MAX_TREE_SIZE] = {0};  //防止重复输出相同孩子信息
    for(int i=0; i<tree->n; i++)
    {
        if(!strcmp(tree->nodes[i].data.name, demo))  //找到是否存在此人
        {
            printf("查询结果:\n");
            p = tree->nodes[i].firstchild;  //指向该成员的孩子域
            while(p != NULL)
            {
                flag = p->child; //得到其孩子在数组中的位置
                if(!book[flag])  //如果这个孩子没有输出过的花,则输出其孩子信息
                {
                    printf("其第%d个孩子的名字是: ",cnt+1);
                    puts(tree->nodes[flag].data.name);  //输出后自动换行
                    book[flag] = 1;
                    cnt++;//统计这个成员的孩子数
                }
                p = p->next;       //指向下一个孩子
            }
            if(cnt == 0)  //如果这个孩子数为0
            {
                printf("此人目前还没有孩子!\n");
            }
            if(-1 == tree->nodes[i].parent)  //如果他是祖先的话,则父亲未知
            {
                printf("家族祖先,其父亲目前尚未知悉!\n");
                show_seniority(tree, i);   //调用显示其辈分的函数
                return OK;  //返回操作成功
            }
            printf("其父亲的名字是: ");
            puts(tree->nodes[(tree->nodes[i].parent)].data.name);
            show_seniority(tree, i);   //调用显示其辈分的函数
            return OK;
        }
    }
    printf("查询结果:\n此家谱中没有此人!\n");
    return ERROR;  //如果在数组中没有找到这个人的姓名,返回查询失败ERROR
}

Status Exist_BothDay(CTree *tree)  //以出生日期判断是否存在此人
{
    int cnt = 0;   //统计孩子数
    int flag;  //得到此节点的孩子在数组的位置
    int exist = 0;   
    int sum = 0; //统计满足此生日的人数
    int book[MAX_TREE_SIZE] = {0}; //标记此成员已经是否被输出过
    char demo[LEN];  //接收输入
    printf("输入你要找的人的生日:");
    gets(demo); 
    ChildPtr * p =NULL;
    printf("查询结果:\n");
    for(int i=0; i<tree->n; i++)  //循环查询满足此生日的成员
    {
        if(!strcmp(tree->nodes[i].data.bothDay, demo))  //如果发现有满足这个出生日期的
        {
            exist = 1;  //标记存在
            printf("满足此生日的第%d个人是",sum+1);
            puts(tree->nodes[i].data.name);
            p = tree->nodes[i].firstchild;  //指向此人的孩子域
            while(p != NULL)  //如果他有孩子的话
            {
                flag = p->child;  //为了防止重复输出,故标记之
                if(!book[flag])
                {
                    printf("其第%d个孩子的名字是: ",cnt+1);
                    puts(tree->nodes[flag].data.name);  //输出后自动换行
                    book[flag] = 1;  //他被输出过,标记为1
                    cnt++;  //统计孩子个数
                }
                p = p->next;        //指向下一个孩子域
            }
            if(cnt == 0)  //如果这个人没有孩子
            {
                printf("此人目前还没有孩子!\n");
            }
            if(-1 == tree->nodes[i].parent)  //如果他的父亲在数组中的位置为-1,则此人为祖先
            {
                printf("家族祖先,其父亲目前尚未知悉!\n");
                
            }
            else
            {
                printf("其父亲的名字是: ");
                puts(tree->nodes[(tree->nodes[i].parent)].data.name);
            }
            sum++;  //继续查询其他人还有满足此出生日期的
            show_seniority(tree, i);   //调用显示其辈分的函数
        }
        cnt = 0;  //查询其他人的是否,把统计孩子的变量赋值为0
    }
    if(!exist)  //如果数组中没有满足此生日的人
    {
        printf("此家谱中没有此人!\n");
        return ERROR;  //返回ERROR,查询失败
    }
    return OK;  //反之,查询操作成功!
}

void Inquire(CTree *tree) //查询功能
{
    int status; //根据返回值反馈操作是否成功
    int choice;  //接收用户的选项
    while((choice = get_choice_Inquire()) != 'q')
    {
        switch (choice)
        {
        case 'a':   
            status = Exist_Name(tree);  //调用按照姓名查询功能
            if(status)  //如果成功查询
            {
                printf("查询操作成功!\n");
            }
            break;
        case 'b':
            status = Exist_BothDay(tree);  //调用按照出生日期查询功能
            if(status)  //如果成功查询
            {
                printf("查询操作成功!\n");
            }
            break;
        case 'q':
        default:
            break;
        }
    }

}

void Add_Child(CTree *tree, int i)  //为数组节点增加孩子 
{
    int sum;
    ChildPtr * ptr = NULL;
    printf("正在准备为第%d个成员完善->孩子<-信息\n",i+1);
    fflush(stdin);  //刷新缓冲区
    printf("请输入该成员的孩子数量:");
    scanf("%d",&sum);   //接收该成员的个数
    getchar();   ///接收换行符号
    if(sum != 0) 
    {
        for(int j=0; j<sum; j++)  //确定每个孩子在数组中的位置
        {
            ptr = (ChildPtr*)malloc(sizeof(ChildPtr));
            if(ptr == NULL)
            {
                printf("分配内存失败!程序终止!");
                exit(-1);
            }
            else
            {
                printf("请输入第%d个->孩子<-在数组中的<下标>:",j+1);
                scanf("%d",&ptr->child);  //接收该孩子在数组中的下标
                getchar();
                ptr->next = tree->nodes[i].firstchild;  //是该成员的孩子域指向此孩子的位置
                tree->nodes[i].firstchild = ptr;//更新下一个孩子的信息
                ptr = NULL;
            }
        }
    }
    else
    {
        printf("此人目前还没有孩子!\n");
    }        
}

void Add_Parent_Init(CTree *tree, int i)  //为数组节点确定父节点 
{
    int flag;  //接收此成员父亲在数组的下标
    if(i == tree->r)  //数组下标为0,为祖先
    {
        tree->nodes[i].parent = -1;
    }
    else
    {
        fflush(stdin);  //刷新缓冲区
        printf("请输入第%d个节点的->父亲<-在数组中的<下标>:",i+1);
        scanf("%d",&flag);  //接收父亲在数组中的下标
        getchar();
        tree->nodes[i].parent = flag;
    }
}
/**
 * 新增加的成员其父亲的初始化和刚刚初始化的时候成员其父亲的初始化有不同之处,不能简单的
 * 像初始化其孩子一样,初始化成员的时候其父亲初始化属于创建单链表,而此时为新增加的成员
 * 初始化其父亲,相当于单链表的插入操作!
 */
void Add_Parent_Person(CTree *tree, int i)
{
    ChildPtr * ptr = NULL;  //同步更新父节点的孩子链表
    int flag;  //此节点父节点所在数组的下标
    fflush(stdin);
    printf("请输入第%d个新成员的->父亲<-在数组中的<下标>:",i+1);
    scanf("%d",&flag);  //接收父亲节点在数组中位置
    getchar();
    tree->nodes[i].parent = flag;  //为此成员的父亲元素填充此父亲节点在数组中的下标
    ptr = (ChildPtr*)malloc(sizeof(ChildPtr));
    if(ptr == NULL)
    {
        printf("分配内存失败!程序终止!");
        exit(-1);
    }
    else
    {
        ptr->child = i;  //更新父亲节点中孩子的指针域,即为父亲节点的孩子域中添加这个新的成员孩子
        ptr->next = tree->nodes[flag].firstchild;
        tree->nodes[flag].firstchild = ptr;
    }
}
Status Add_Person(CTree *tree)
{
    int sum;  //确定新增加成员的人数
    int cnt = tree->n;  //之前已经存在的人数
    printf("输入你准备增加的人数:");
    scanf("%d",&sum);
    getchar();
    tree->n += sum;  //更新总人数
    printf("请依次输入各个人的信息:\n");
    for(int i=0; i<sum; i++)   //为每一个新成员完善信息
    {
        printf("***********\t正在完善第%d个新成员的信息:\t***********\n",i+1);
        fflush(stdin);  //刷新缓冲区
        tree->nodes[cnt+i].data = Input();  //调用函数,初始化新增成员的个人基本信息
        tree->nodes[cnt+i].firstchild = NULL;  //
        tree->nodes[cnt+i].parent = -1;
        Add_Child(tree, cnt+i);
        Add_Parent_Person(tree, cnt+i);
        printf("**************************************************\n");
    }
    return OK;  //如果成功添加
}

Status Remove(CTree *tree)  //删除某人
{
    int cnt = 0;
    printf("请输入要从家谱中移除的姓名:");
    int flag;  //确定要删除的人在数组中的下标
    int exist = 0;  //判断此人是否在家谱中存在
    char demo[LEN];//接收要删除人的姓名
    gets(demo); 
    for(int i=0; i<tree->n; i++)
    {
        if(!strcmp(tree->nodes[i].data.name, demo))  //判断此数组中有没有要删除的人
        {
            flag = i;
            exist = 1; //标记,说明此数组中存在这个人
            break;
        }

    }
    if(exist)  //如果存在这个人的话
    {
        for(int i=flag; i<tree->n; i++)
        {
            tree->nodes[i] = tree->nodes[i+1];  //让这个人所在数组中后面的人往期移一个位置
        }
        tree->n--;
        return OK;  //删除操作成功
    }
    return ERROR;   //没有找到这个人,删除操作失败
}   

Status Modify(CTree *tree)  //修改某人信息
{
    int flag = -1; 
    char demo[LEN];  //接收要删除人的姓名
    printf("输入你要修改的人的名字:");
    gets(demo); 
    for(int i=0; i<tree->n; i++)
    {
        if(!strcmp(tree->nodes[i].data.name, demo))  //查找是否存在此人
        {
            flag = i;  //接收这个人在数组中下标位置
            break;
        }
    }
    if(flag == -1)  //如果数组中没有这个人
    {
        return ERROR;  //修改操作失败
    }
    int choice;  //接收选项
    memset(demo, '0', LEN);  //初始化该数组
    while((choice = get_choice_Modify()) != 'q')
    {
        switch (choice)
        {
        case 'a':
            printf("请重新编辑此人姓名:");
            gets(demo);
            strcpy(tree->nodes[flag].data.name, demo);
            break;
        case 'b':
            printf("请重新编辑此人出生日期:");
            gets(demo);
            strcpy(tree->nodes[flag].data.bothDay, demo);  //把新的名字赋值给该成员
            break;
        case 'c':
            printf("请重新编辑此人是否健在:");
            scanf("%d",&tree->nodes[flag].data.keepAlive);   //更新此人是否健在状况
            getchar();
            if(tree->nodes[flag].data.keepAlive == 0)  //如果其死亡
            {
                printf("输入死亡日期:");
                gets(tree->nodes[flag].data.deathDay);    //更新此人的死亡日期
            }
            break;
        case 'd':
            printf("请重新编辑此人编辑是否已婚:");
            scanf("%d",&tree->nodes[flag].data.getMatings);  //更新此人是否已婚
            getchar();
            break;
        case 'q':
        default:
            break;
        }
    }
    return OK;
}
/**
 * 对一个成员数组按照出生日期进行排序,应该慎重的选择排序算法,此处相当于桶排序,因为不能让成员在数组
 * 中的位置发生变化,否则其孩子将失效,并且也不能单独改变生日在数组中下标,所以此处一些常见的排序算法
 * 我目前不知如何应用,故采用桶排序远离,去创建一个数组,其下标从小到大顺序存储按照生日排序成员在数组中过的
 * 下标位置
 */ 
Status Sort_BothDay(CTree *tree)  //对家谱里的人进行排序
{
    int sort[MAX_TREE_SIZE] = {0};  //该数组用于接收排序后的成员的下标值
    char min_string[MAX_TREE_SIZE] = {'\0'};
    int min_int;
    int book[MAX_TREE_SIZE] = {0};  //用于标记已经排好序的成员
    int i = 0;
    int cnt = 0;  //统计排好序的人数
    while(i < tree->n)  
    {
        min_int = i;
        strcpy(min_string, tree->nodes[i].data.bothDay);
        while(book[i] != 0)
        {
            i++;    //检索数组下标
            min_int = i;    //假设此时最小成员的数组下标为i
            strcpy(min_string, tree->nodes[i].data.bothDay);  
        }
        for(int j=0; j<tree->n; j++)
        {
            if((book[j]==0)&&(i!=j)&&strcmp(min_string, tree->nodes[j].data.bothDay)>0)
            {
                min_int = j;
                strcpy(min_string, tree->nodes[j].data.bothDay);
            }
        }
        sort[cnt++] = min_int;
        book[min_int] = 1;
        i = 0;
        if(cnt == tree->n)
        {
            break;
        }
    }
    printf("按出生日期进行排序:\n");
    for (int i = 0; i < tree->n; i++)
    {
        printf("第%d个人是%s,他的出生日期为:%s\n",i+1, tree->nodes[sort[i]].data.name,tree->nodes[sort[i]].data.bothDay);
    }
    return OK;  //排序操作成功,返回操作成功!
}

void Destroy(CTree *tree)
{
    ChildPtr * p = NULL;
    ChildPtr * q = NULL;
    for (int i = 0; i < tree->n; i++)
    {
        p = tree->nodes[i].firstchild;
        q = p;
        while(p)
        {
            p = p->next;
            free(q);
            q = p;
        }
    }
} 

void Data_write(CTree *tree)
{
    printf("👇即将把数据存入文本文件中>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
    const char *file = "homefamily.txt";
    ofstream outfile(file, ios::trunc);
    if(!outfile)
    {
        printf("文件打开失败!\n");
        exit(-1);   
    }
    else
    {
        outfile<<"成员姓名"<<"\t"<<"出生日期"<<"\t"<<"家庭地址"<<endl;
        for (int i = 0; i < tree->n; i++)
        {   
            outfile<<tree->nodes[i].data.name<<"\t"<<tree->nodes[i].data.bothDay<<"\t"<<tree->nodes[i].data.address<<endl;
        }
        outfile.close();
        printf("程序数据写入文件成功!!\n");
    }
}

主函数:treeco.cpp

#include "treeheader.h"
int main()
{
    CTree ctree;
    User_login(&ctree);  //用户登录函数
    return 0;
}

运行示例:

➜  TreeDemo g++ implements.cpp treeco.cpp -o Tree
➜  TreeDemo ./Tree
***********     欢迎登陆家族管理系统    ***********
warning: this program uses gets(), which is unsafe.
输入您的用户名:user_super
请输入管理员密码:123123
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
a
请确定初始化家谱信息需要的成员数量:4
请依次输入各个人的信息:

***********     正在完善第1个成员的信息:       ***********
成员姓名:jia
出生日期:19991005
成员住址:nanjing
是否结婚(0/1):0
是否健在(0/1):1
正在准备为第1个成员完善->孩子<-信息
请输入该成员的孩子数量:2
请输入第1->孩子<-在数组中的<下标>:1
请输入第2->孩子<-在数组中的<下标>:2
**********************************************
***********     正在完善第2个成员的信息:       ***********
成员姓名:yi
出生日期:19960405
成员住址:chengdu
是否结婚(0/1):1
是否健在(0/1):1
正在准备为第2个成员完善->孩子<-信息
请输入该成员的孩子数量:1
请输入第1->孩子<-在数组中的<下标>:3
请输入第2个节点的->父亲<-在数组中的<下标>:0
**********************************************
***********     正在完善第3个成员的信息:       ***********
成员姓名:bing
出生日期:20040503
成员住址:beijing
是否结婚(0/1):1
是否健在(0/1):1
正在准备为第3个成员完善->孩子<-信息
请输入该成员的孩子数量:0
此人目前还没有孩子!
请输入第3个节点的->父亲<-在数组中的<下标>:0
**********************************************
***********     正在完善第4个成员的信息:       ***********
成员姓名:ding
出生日期:19991005
成员住址:shanghai
是否结婚(0/1):0
是否健在(0/1):1
正在准备为第4个成员完善->孩子<-信息
请输入该成员的孩子数量:0
此人目前还没有孩子!
请输入第4个节点的->父亲<-在数组中的<下标>:1
**********************************************
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
f 
按出生日期进行排序:
第1个人是yi,他的出生日期为:199604052个人是jia,他的出生日期为:199910053个人是ding,他的出生日期为:199910054个人是bing,他的出生日期为:20040503
排序操作成功!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
c
输入你准备增加的人数:2
请依次输入各个人的信息:
***********     正在完善第1个新成员的信息:     ***********
成员姓名:wu    
出生日期:20050401
成员住址:chongqing
是否结婚(0/1):1
是否健在(0/1):1
正在准备为第5个成员完善->孩子<-信息
请输入该成员的孩子数量:1
请输入第1->孩子<-在数组中的<下标>:3
请输入第5个新成员的->父亲<-在数组中的<下标>:1
**************************************************
***********     正在完善第2个新成员的信息:     ***********
成员姓名:hua
出生日期:20050401
成员住址:suzhou
是否结婚(0/1):1
是否健在(0/1):1
正在准备为第6个成员完善->孩子<-信息
请输入该成员的孩子数量:1
请输入第1->孩子<-在数组中的<下标>:6
请输入第6个新成员的->父亲<-在数组中的<下标>:-1
**************************************************
添加新成员成功!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
h
👇即将把数据存入文本文件中>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
程序数据写入文件成功!!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
c
输入你准备增加的人数:2
请依次输入各个人的信息:
***********     正在完善第1个新成员的信息:     ***********
成员姓名:cao
出生日期:20060504
成员住址:nantong
是否结婚(0/1):1
是否健在(0/1):1
正在准备为第7个成员完善->孩子<-信息
请输入该成员的孩子数量:0
此人目前还没有孩子!
请输入第7个新成员的->父亲<-在数组中的<下标>:5
**************************************************
***********     正在完善第2个新成员的信息:     ***********
成员姓名:shu
出生日期:20040504
成员住址:xuzhou
是否结婚(0/1):1
是否健在(0/1):1
正在准备为第8个成员完善->孩子<-信息
请输入该成员的孩子数量:0
此人目前还没有孩子!
请输入第8个新成员的->父亲<-在数组中的<下标>:-1
**************************************************
添加新成员成功!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
h
👇即将把数据存入文本文件中>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
程序数据写入文件成功!!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
e
输入你要修改的人的名字:ding
欢迎使用此家族管理系统的修改系统!!!
a.  编辑姓名                     b.  编辑出生日期
c.  编辑是否健在                  d.  编辑是否已婚
a
请重新编辑此人姓名:xiaoming
欢迎使用此家族管理系统的修改系统!!!
a.  编辑姓名                     b.  编辑出生日期
c.  编辑是否健在                  d.  编辑是否已婚
q
修改此人操作成功!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
h
👇即将把数据存入文本文件中>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
程序数据写入文件成功!!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
d
请输入要从家谱中移除的姓名:shu
删除此人操作成功!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
h
👇即将把数据存入文本文件中>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
程序数据写入文件成功!!
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
g
                欢迎使用此家族管理系统!!!
*************************************
Enter the letter of your choice:
a.  初始化家族谱                b.  查询信息
c.  增加新成员                  d.  删除成员
e.  修改成员                    f.  按生日进行排序
g.  释放内存                    h.  存入文本文件
**************q.    退出程序***********
q

图片
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 8
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ocodotial

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值