婚姻管理系统-使用bbst数据结构

使用到希尔排序和归并排序,文件存储

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include

//名字的最大长度
#define NameMax 30

//全局的文件指针变量
FILE* file, * file_admin, * file_divorce;

//结婚人数
int nums = 0;

//定义普通用户的结构体
typedef struct user {
    char name[NameMax];
    char ID[20];    //身份证位18位
    int age;            //年龄
    char sex;       //性别,F位女,M为男
    char partner[NameMax];  //配偶的名字
    char partner_ID[20];    //配偶的身份证
    struct user* next;
} User;

//定义管理员的结构体
typedef struct admin {
    char name[NameMax]; //管理员的名字
    char password[20];      //密码
}Admin;

//定义树结点信息
typedef struct node {
    int height;
    int balance;
    User* info;
    struct node* left;
    struct node* right;
}Node;

//离婚人数链表,用来存储离婚人的信息
User* divorce;

//判断是否操作确认,确认是返回1,不确认返回0
int GetConfirm()
{
    char yes_no[5];
    memset(yes_no, 0, sizeof(yes_no));
    printf("\n\t\t=======================================\n");
    printf(" \n\t\t\t是否执行该操作 ? 此操作不可逆! \n");
    printf("\n\t\t=======================================\n");
    printf("\n\t\t\t确认? [Y/N]:");
    scanf("%s", yes_no);
    if (strcmp(yes_no, "y") == 0 || strcmp(yes_no, "Y") == 0)
        return 1;
    else
        return 0;
}

//获得树的高度
int getHeight(Node* node) {
    if (node == NULL) {
        return 0;
    }
    int leftHeight = getHeight(node->left);
    int rightHeight = getHeight(node->right);
    return max(leftHeight, rightHeight) + 1;
}

//获得当前结点的平衡因子
int getBalanceFactor(Node* tree) {
    //如果不为空,当前结点平衡因子为左子树高度-右子树高度
    if (tree) {
        return getHeight(tree->left) - getHeight(tree->right);
    }
    return 0;
}

//左转
Node* RR(Node* parent) {
    //左旋
    Node* son = parent->left;
    parent->left = son->right;
    son->right = parent;
    //更新结点的高度
    son->height = max(getHeight(son->left), getHeight(son->right)) + 1;
    parent->height = max(getHeight(parent->left), getHeight(parent->right)) + 1;
    //返回当前在最顶上的结点
    return son;
}

//左旋
Node* LL(Node* parent) {
    //左旋变换
    Node* son = parent->right;
    parent->right = son->left;
    son->left = parent;
    //更新结点高度
    son->height = max(getHeight(son->left), getHeight(son->right)) + 1;
    parent->height = max(getHeight(parent->left), getHeight(parent->right)) + 1;
    //返回当前在最顶上的结点
    return son;
}


//更新树的平衡
Node* balance(Node* node) {

    //获取当前节点的平衡因子
    int bf = getBalanceFactor(node);

    //不需要平衡
    if (bf == 0)
        return node;

    if (bf > 1) {
        //左子树比右子树高
        if (getBalanceFactor(node->left) < 0) {
            //LR型,先对左节点进行LL旋转再对当前结点进行RR旋转
            node->left = LL(node->left);
        }
        node = RR(node);
    }
    else if (bf < -1) {
        //右子树比左子树高
        if (getBalanceFactor(node->right) > 0) {
            //RL型,先对右节点进行RR旋转再对当前结点进行LL旋转
            node->right = RR(node->right);
        }
        node = LL(node);
    }

    // 更新节点高度
    node->height = max(getHeight(node->left), getHeight(node->right)) + 1;

    return node;
}

//返回一个正确的身份证号
char* correct_ID() {
    char* str = (char*)malloc(sizeof(char) * 19);
    memset(str, 0, sizeof(str));
    scanf("%s", str);
    while (strlen(str) != 18) {
        printf("\t\t身份证出错,请输入身份证:");
        scanf("%s", str);
        putchar('\n');
    }
    return str;
}

//插入一个节点数据
Node* insert(Node* tree, User* info) {
    // 判断插入节点是否为空
    if (info == NULL) {
        return tree;
    }

    // 创建插入节点并赋值
    if (tree == NULL) {
        //判断是否离婚
        User* p, * temp;
        temp = p = divorce;
        while (temp) {
            if (!strcmp(temp->ID, info->ID)) {
                printf("\n\t          此人已离婚!!!是否继续?\n");
                if (GetConfirm()) {
                    p->next = temp->next;
                }
                else
                    return tree;
            }
            p = temp;
            temp = temp->next;
        }

        nums++;
        tree = (Node*)malloc(sizeof(Node));
        tree->info = (User*)malloc(sizeof(User));
        *(tree->info) = *info;
        tree->info->next = NULL;
        tree->height = 0;
        tree->left = tree->right = NULL;
        return tree;
    }

    // 存在相同身份证号的情况
    if (strcmp(info->ID, tree->info->ID) == 0) {
        printf("\t          身份证重复或已存在该人的信息,添加失败!\n");
        return NULL;
    }
    else if (strcmp(info->ID, tree->info->ID) < 0) {
        tree->left = insert(tree->left, info);
    }
    else {
        tree->right = insert(tree->right, info);
    }

    // 更新节点高度并进行平衡操作
    tree->height = max(getHeight(tree->left), getHeight(tree->right)) + 1;
    tree = balance(tree);

    return tree;
}

//按身份证来查找某个结点
User* searchByID(Node* tree, char* ID) {
    if (ID == NULL) {
        printf("身份证出错");
        return NULL;
    }

    if (!tree) {
        User* p = divorce->next;
        int flag = 0;
        while (p) {
            if (!(strcmp(p->ID, ID))) {
                printf("\t          姓名:%s,\t\t年龄:%d,\t身份证:%s,\t性别:%c,\t前配偶:%s\n",
                    p->name, p->age, p->ID, p->sex, p->partner);
                flag = 1;
            }
            p = p->next;
        }
        if (flag == 0)
            printf("\n\t          未找到该人的信息!\n");
        return NULL;
    }
    else if (strcmp(ID, tree->info->ID) < 0) {
        return searchByID(tree->left, ID);
    }
    else if (strcmp(ID, tree->info->ID) > 0) {
        return searchByID(tree->right, ID);
    }
    else {
        //找到了,输出信息
        printf("\t          姓名:%s,\t\t年龄:%d,\t身份证:%s,\t性别:%c,\t配偶:%s\n",
            tree->info->name, tree->info->age, tree->info->ID, tree->info->sex, tree->info->partner);
        return tree->info;
    }
}

//通过姓名来查找,通过前序遍历一遍树
int  searchByName(Node* tree, char* name, int type) {
    //结婚的中选取
    if (type == 1) {
        if (name == NULL) {
            printf("名称输入有误");
            return 0;
        }

        if (tree) {
            if (!strcmp(tree->info->name, name)) {
                //找到了,输出信息
                printf("\t          姓名:%s,\t\t年龄:%d,\t身份证:%s,\t性别:%c,\t配偶:%s\n",
                    tree->info->name, tree->info->age, tree->info->ID, tree->info->sex, tree->info->partner);
                return 1;
            }
            return searchByName(tree->left, name, type) + searchByName(tree->right, name, type);
        }
    }
    else {
        //离婚的中查询
        if (divorce == NULL)
            return 0;

        User* q = divorce->next;
        int times = 0;
        while (q) {
            if (!strcmp(q->name, name))
            {
                //找到了相同名字的人
                times++;
                printf("\t          姓名:%s,\t\t年龄:%d,\t身份证:%s,\t性别:%c,\t配偶:%s\n",
                    q->name, q->age, q->ID, q->sex, q->partner);
            }
            q = q->next;
        }
        if (times > 0)
            return 1;
    }
    return 0;
}

//查找替换节点
Node* findrepalceNode(Node* node) {
    //找到右子树上最小节点或左子树上的最大节点


    if (node->left != NULL) {
        //左子树的最大节点
        Node* max = node->left;
        while (max->right != NULL) {
            max = max->right;
        }
        return max;
    }
    else if (node->right != NULL) {
        //右子树的最小节点
        Node* min = node->right;
        while (min->left != NULL) {
            min = min->left;
        }
        return min;
    }
    else {
        //两种都不是
        return NULL;
    }

}

//是否确认输入
int yes_no_divorce() {
    char yes_no[5];
    memset(yes_no, 0, sizeof(yes_no));
    printf("\n\t\t=======================================\n");
    printf(" \n\t\t\t是否为离婚? \n");
    printf("\n\t\t=======================================\n");
    printf("\n\t\t\t y 是离婚   n 是删除 [Y/N]:");
    scanf("%s", yes_no);
    //清空缓存区
    fflush(stdin);
    if (strcmp(yes_no, "y") == 0 || strcmp(yes_no, "Y") == 0)
        return 1;
    else
        return 0;
}

//删除一个结点
Node* del(Node* tree, User* info) {
    // 判断传入的 info 是否为空
    if (info == NULL || tree == NULL || ((tree->right == NULL) && (tree->left == NULL) && strcmp(tree->info->ID, info->ID)==0)) {
        return NULL;
    }

    if (strcmp(info->ID, tree->info->ID) > 0) {
        // 递归删除右子树中的节点
        tree->right = del(tree->right, info);
    }
    else if (strcmp(info->ID, tree->info->ID) < 0) {
        // 递归删除左子树中的节点
        tree->left = del(tree->left, info);
    }
    else {
        // 找到了要删除的节点
        nums--;

        if (tree->left == NULL || tree->right == NULL) {
            // 被删除的节点有一个子节点或者没有子节点

            // 用子节点来代替当前节点
            Node* child;
            if (tree->left == NULL) {
                child = tree->right;
            }
            else {
                child = tree->left;
            }
            free(tree->info);
            free(tree);
            return child;
        }
        else {
            // 被删除的节点有两个子节点
            Node* replacenode = findrepalceNode(tree);
            tree->info = replacenode->info;
            tree->right = del(tree->right, replacenode->info);
        }
    }

    // 更新节点高度并进行平衡操作
    tree->height = max(getHeight(tree->left), getHeight(tree->right)) + 1;
    tree = balance(tree);
    return tree;
}

//显示已结婚所有数据,通过前序遍历实现
void display_tree(Node* tree) {
    if (tree) {
        printf("\t          姓名:%s,\t\t年龄:%d,\t身份证:%s,\t性别:%c,\t配偶:%s\n",
            tree->info->name, tree->info->age, tree->info->ID, tree->info->sex, tree->info->partner);
        display_tree(tree->left);
        display_tree(tree->right);
    }
}

//添加一个双方的婚姻信息(添加婚姻信息)
Node* add_both(Node* tree) {
    //定义好变量
    char name[NameMax];
    char partner_name[NameMax];
    char* ID;
    char* partner_ID;
    int age;
    int partner_age;
    char sex;
    int partner_sex;

    //输入一方的结婚信息
    printf("\t\t          请输入姓名:");
    scanf("%s", name);
    printf("\t\t          请输入身份证:");
    ID = correct_ID();
    printf("\t\t          请输入年龄:");
    getchar();
    scanf("%d", &age);
    printf("\t\t          请输入性别(M/F):");
    getchar();
    scanf(" %c", &sex);
    printf("\t\t          请输入配偶姓名:");
    scanf("%s", partner_name);
    printf("\t\t          请输入配偶身份证:");
    partner_ID = correct_ID();
    printf("\t\t          请输入配偶年龄:");
    getchar();
    scanf("%d", &partner_age);
    printf("\t\t          请输入配偶性别(M/F):");
    getchar();
    scanf(" %c", &partner_sex);
    getchar();

    User* info = (User*)malloc(sizeof(User));
    (info->next) = NULL;
    User* info2 = (User*)malloc(sizeof(User));
    (info2->next) = NULL;

    if (GetConfirm()) {
        info->age = age;
        info->sex = sex;
        strcpy(info->name, name);
        strcpy(info->ID, ID);
        strcpy(info->partner, partner_name);
        strcpy(info->partner_ID, partner_ID);
        //先插入本人的身份信息到树中
        printf("\t          姓名:%s,年龄:%d,身份证:%s,性别:%c,配偶:%s\n",
            info->name, info->age, info->ID, info->sex, info->partner);
        tree = insert(tree, info);

        //复制配偶的信息

        info2->age = partner_age;
        info2->sex = partner_sex;
        strcpy(info2->name, partner_name);
        strcpy(info2->ID, partner_ID);
        strcpy(info2->partner, name);
        strcpy(info2->partner_ID, ID);
        printf("\t         姓名:%s,年龄:%d,身份证:%s,性别:%c,配偶:%s\n",
            info2->name, info2->age, info2->ID, info2->sex, info2->partner);
        //先插入配偶的身份信息到树中
        tree = insert(tree, info2);

    }

    return tree;
}

//删除一个双方婚姻信息
Node* del_node(Node* tree) {
    if (nums <= 2) {
        printf("\t          节点必须多于两个\n");
        return tree;
    }
    char* del_ID;
    char del_partnerID[20];
    //输入信息
    printf("\t\t          请输入要删除人的身份证:");
    del_ID = correct_ID();
    //查找节点
    User* user1, * user2;
    user1 = searchByID(tree, del_ID);
    if (user1 == NULL)
        return tree;
    strcpy(del_partnerID, user1->partner_ID);
    user2 = searchByID(tree, del_partnerID);

    if (GetConfirm()) {
        if (yes_no_divorce()) {
            //返回值为1,代表离婚
            User* p, * q;
            p = q = divorce;
            if (divorce->next != NULL) {
                //遍历到链表的最后一个节点
                while (q) {
                    p = q;
                    q = q->next;
                }
            }
            //插入离婚两人的信息在链表中
            q = (User*)malloc(sizeof(User));
            q->next = NULL;
            (*q) = (*user1);
            (p->next) = q;
            p = (p->next);
            q = (User*)malloc(sizeof(User));
            q->next = NULL;
            (*q) = (*user2);
            p->next = q;
            q->next = NULL;
        }
        //删除节点
        tree = del(tree, user1);
        tree = del(tree, user2);

    }
    return tree;

}

//登入
Admin* login(Admin* admin) {
    if (admin == NULL)
    {
        printf("admin.txt文件出错");
        exit(0);
    }

    char admin_name[NameMax];
    char admin_password[20];
    int times = 0;
    while (1) {
        //输入管理信息
        printf("\t          请输入管理员账号:");
        scanf("%s", admin_name);
        printf("\n");
        printf("\t          请输入管理员密码:");
        scanf("%s", admin_password);

        //判断管理员信息是否相等
        if (!strcmp(admin->name, admin_name)) {
            if (!strcmp(admin->password, admin_password))
                break;
            else
            {
                printf("\t          密码错误,请重新输入:\n\n");
            }
        }
        else
        {
            printf("\t          管理员账号错误,请重新输入:\n\n");
        }

        times++;
        //如果密码多次出错
        if (times > 4) {
            printf("\t\t是否需要修改密码:\n");
            if (GetConfirm()) {
                printf("请输入修改的用户名:\n");
                scanf("%s", admin->name);
                printf("请输入修改的密码:\n");
                scanf("%s", admin->password);
            }
        }
    }
    return admin;
}


//调用文件初始化一颗二叉树
Node* readFile(FILE* f) {
    Node* tree = (Node*)malloc(sizeof(Node));
    tree->info = (User*)malloc(sizeof(User));
    tree->info = NULL;
    tree = NULL;
    User* temp = (User*)malloc(sizeof(User));
    temp->next = NULL;
    //判断文件是否为空
    fseek(f, 0, SEEK_END);
    long position = ftell(f);
    if (position == 0) {
        //printf("文件为空\n");
        return NULL;
    }
    //文件移到开头
    fseek(f, 0, SEEK_SET);
    while (fscanf(f, "%s %s %d %c %s %s\n", temp->name, temp->ID, &temp->age, &temp->sex, temp->partner, temp->partner_ID) != EOF) {
        tree = insert(tree, temp);

        //注意指针一次只能指向一个地址,新建一棵树的时候要不断的来创建一个地址空间
        temp = (User*)malloc(sizeof(User));
        temp->next = NULL;
    }
    return tree;
}

//磁盘上读取一个admin文件出来
Admin* readAdmin(FILE* f) {
    Admin* temp = (Admin*)malloc(sizeof(Admin));


    fseek(f, 0, SEEK_SET);
    fscanf(f, "%s\n%s", temp->name, temp->password);
    return temp;
}

//磁盘上读取一个divorve文件出来
User* readDivorce(FILE* f) {
    User* p, * q, * divorce;
    p = q = divorce = (User*)malloc(sizeof(User));
    p->next = NULL;
    q = (User*)malloc(sizeof(User));
    q->next = NULL;
    //判断文件是否为空
    fseek(f, 0, SEEK_END);
    long position = ftell(f);
    if (position == 0) {
        //printf("文件为空\n");
        User* temp = (User*)malloc(sizeof(User));
        (temp->next) = NULL;
        return temp;
    }
    //文件移到开头
    fseek(f, 0, SEEK_SET);
    while ((fscanf(f, "%s %s %d %c %s %s\n", q->name, q->ID, &q->age, &q->sex, q->partner, q->partner_ID)) != EOF)
    {
        p->next = q;
        p = p->next;
        q = (User*)malloc(sizeof(User));
    }
    free(q);
    p->next = NULL;
    return divorce;
}


//前序遍历存储树到文件中
void travel_creatfile(Node* root) {
    if (root == NULL || file == NULL) {
        return;
    }

    fprintf(file, "%s %s %d %c %s %s\n",
        root->info->name, root->info->ID, root->info->age, root->info->sex,
        root->info->partner, root->info->partner_ID);
    //遍历树
    travel_creatfile(root->left);
    travel_creatfile(root->right);
}


User* h, * p;

//树转换成链表
void User_to_list(Node* root) {
    if (root == NULL)
        return;
    p->next = root->info;
    p = p->next;
    p->next = NULL;
    User_to_list(root->left);
    User_to_list(root->right);
}

//保存文件
void saveTreeToFile(Node* temp) {
    fclose(file);
    if ((file = fopen("marriage.txt", "w+")) != NULL) {
        //打开成功
        ;
    }
    else {
        //打开失败
        printf("文件打开出错:\n");
        exit(0);
    }
    travel_creatfile(temp);
}

//保存离婚信息文件
void saveDivorceToFile(User* divorce_temp) {
    fclose(file_divorce);
    if ((file_divorce = fopen("divorce.txt", "w+")) != NULL) {
        //打开成功
        ;
    }
    else {
        //打开失败
        printf("文件打开出错:\n");
        exit(0);
    }
    if (divorce_temp == NULL)
        return;
    User* divorce = divorce_temp->next;
    //循环遍历链表,将链表数据存储到文件中
    while (divorce) {
        fprintf(file_divorce, "%s %s %d %c %s %s\n",
            divorce->name, divorce->ID, divorce->age, divorce->sex, divorce->partner, divorce->partner_ID);
        divorce = divorce->next;
    }
}

//保存管理员信息文件
void saveAdminToFile(Admin* admin) {

    fclose(file_admin);

    if ((file_admin = fopen("admin.txt", "w+")) != NULL) {
        //打开成功
        ;
    }
    else {
        //打开失败
        printf("\t          管理员信息文件打开出错:\n");
        exit(0);
    }
    if (fprintf(file_admin, "%s\n%s", admin->name, admin->password) == EOF) {
        printf("\t          管理员信息文件保存出错:\n");
    }
}

//统计结婚信息
void Statistical(User a[]) {
    //定义并初始化数组
    int aa[11] = { 0 };

    for (int i = 0; i < nums; i++) {
        aa[a[i].age / 10]++;
    }
    printf("\n\t\t不同年龄阶段登记结婚统计:\n");
    for (int i = 1; i < nums; i++)
        printf("\n\t\t%d岁到%d岁之间有:%d人", i * 10, (i + 1) * 10 - 1, aa[i]);
    putchar('\n');
}

//希尔排序,升序排序
void shell_sort(User arr[], int type) {
    // 初始步长
    int gap = nums / 2;
    while (gap > 0) {
        for (int i = gap; i < nums; i++) {
            User temp = arr[i];
            int j = i - gap;
            //进行比较
            if (type == 0) {
                //升序
                while (j >= 0 && arr[j].age > temp.age) {
                    arr[j + gap] = arr[j];
                    j -= gap;
                }
            }
            else {
                while (j >= 0 && arr[j].age < temp.age) {
                    arr[j + gap] = arr[j];
                    j -= gap;
                }
            }
            //交换
            arr[j + gap] = temp;
        }
        gap /= 2; // 缩短步长
    }
}

//年龄排序
void sort_age(Node* tree) {
    if (tree == NULL) {
        printf("\t\t无数据\n");
        return;
    }
    p = h = (User*)malloc(sizeof(User));
    h->next = NULL;
    User_to_list(tree);
    p->next = NULL;

    User* pp, * head = h->next;
    if (head == NULL)
    {
        printf("\t\t无信息\n");
        return;
    }
    User* a = (User*)malloc(sizeof(User) * nums);
    int i = 0;
    while (head) {
        pp = head;
        *(a + i) = *head;
        i++;
        head = head->next;
        pp->next = NULL;
    }
    //进行排序
    printf("\t\t升序排序请输入0,降序则输入其他\n");
    int type;
    printf("\t\t请输入你要输入的:");
    scanf("%d", &type);
    shell_sort(a, type);
    putchar('\n');
    for (i = 0; i < nums; i++) {
        printf("\t         姓名:%s,\t\t年龄:%d,\t身份证:%s,\t性别:%c,\t配偶:%s\n",
            a[i].name, a[i].age, a[i].ID, a[i].sex, a[i].partner);
    }
    getchar();
    Statistical(a);

    free(a);
}

//查看离婚人数列表
void display_divorce() {
    int divorce_num = 0;
    if (divorce == NULL)
    {
        printf("\t        无\n");
        return;
    }
    User* p = divorce->next;
    while (p) {
        printf("\t         姓名:%s,年龄:%d,身份证:%s,性别:%c,前配偶:%s\n",
            p->name, p->age, p->ID, p->sex, p->partner);
        divorce_num++;
        p = p->next;
    }
    printf("\t\t\t离婚人数有:   %d", divorce_num);
}

//显示所有信息
void display_all(Node* tree) {
    printf("\t\t已结婚:\n");
    display_tree(tree);
    printf("\t\t已离婚:\n");
    display_divorce();
}

//查找并改写该结婚信息
Node* searchcorrect_mar(Node** tree, char* ID) {
    if (((*tree) == NULL) || ID == NULL)
        return *tree;
    if (strcmp(ID, (*tree)->info->ID) > 0) {
        //在右子树中
        searchcorrect_mar(&((*tree)->right), ID);
    }
    else if (strcmp(ID, (*tree)->info->ID) < 0) {
        searchcorrect_mar(&((*tree)->left), ID);
    }
    else {
        //找到节点了
        printf("\t\t          请输入要更改的姓名:");
        char name[NameMax];
        scanf("%s", name);
        putchar('\n');
        strcpy((*tree)->info->name, name);
        printf("\t\t          请输入要更改的性别:");
        char sex;
        //抵消多余的回车
        getchar();
        scanf(" %c", &sex);
        putchar('\n');
        printf("\t\t          请输入要更改的年龄:");

        getchar();
        int age;
        scanf("%d", &age);
        (*tree)->info->sex = sex;
        (*tree)->info->age = age;
        return (*tree);
    }
}

void searchcorrect_mar2(Node** tree, User* info) {
    if (((*tree) == NULL) || info->ID == NULL)
        return;
    if (strcmp(info->ID, (*tree)->info->ID) > 0) {
        //在右子树中
        searchcorrect_mar2(&((*tree)->right), info);
    }
    else if (strcmp(info->ID, (*tree)->info->ID) < 0) {
        searchcorrect_mar(&((*tree)->left), info);
    }
    else {
        //找到节点了
        strcpy((*tree)->info->partner, info->name);
    }
}

//更改婚姻信息
Node* correct_marriage(Node* tree) {
    User* newnode = (User*)malloc(sizeof(User));
    char* ID;
    printf("\t\t输入你要更改人的身份证:  ");
    ID = correct_ID();
    if (ID == NULL) {
        printf("输入出错");
        exit(0);
    }
    Node* temp = searchcorrect_mar(&tree, ID);
    if (temp != temp)
        searchcorrect_mar2(&tree, temp->info);   //在结婚信息中找到节点了
    else {
        User* p = divorce->next;
        printf("\t\t          请输入要更改的姓名:");
        char name[NameMax];
        scanf("%s", name);
        putchar('\n');
        printf("\t\t          请输入要更改的性别:");
        char sex;
        //抵消多余的回车
        getchar();
        scanf(" %c", &sex);
        putchar('\n');
        printf("\t\t          请输入要更改的年龄:");
        getchar();
        int age;
        scanf("%d", &age);
        while (p) {
            if (!strcmp(p->ID, ID)) {
                //在离婚信息中找到节点了
                strcpy(p->name, name);
                p->sex = sex;
                p->age = age;
            }
            p = p->next;
        }
    }
    return tree;
}

//更改管理员信息
Admin* correct_admin() {
    if (file_admin == NULL) {
        printf("Admin信息文件出错");
        exit(0);
    }
    else
        fclose(file_admin);

    Admin* new = (Admin*)malloc(sizeof(Admin));
    printf("\t\t输入你要更改人的管理员账号:  ");
    scanf("%s", new->name);
    printf("\t\t输入你要更改人的管理员密码:  ");
    scanf("%s", new->password);
    //判断存储管理员信息的文件是否存在,是否能打开
    if ((file_admin = fopen("admin.txt", "w+")) != NULL) {
        //打开成功
        ;
    }
    else {
        //打开失败
        printf("\t          管理员信息文件打开出错:\n");
        exit(0);
    }
    if (fprintf(file_admin, "%s\n%s", new->name, new->password) == EOF) {
        printf("\t          管理员信息文件保存出错:\n");
    }
    fclose(file_admin);
    return new;
}

//打印菜单
void memu() {

    printf("\n\t\t***************************************\n");
    printf("\t\t*          请选择要进行的操作:       *\n");
    printf("\t\t*          1. 添加婚姻信息            *\n");
    printf("\t\t*          2. 删除婚姻信息            *\n");
    printf("\t\t*          3. 按身份证查询            *\n");
    printf("\t\t*          4. 显示信息                *\n");
    printf("\t\t*          5. 修改婚姻信息            *\n");
    printf("\t\t*          6. 按姓名查询              *\n");
    printf("\t\t*          7. 按年龄进行排序          *\n");
    printf("\t\t*          8. 清屏                    *\n");
    printf("\t\t*          9. 显示菜单                *\n");
    printf("\t\t*          a. 修改管理员信息          *\n");
    printf("\t\t*          b. 保存并退出              *\n");
    printf("\t\t*          c. 保存文件                *\n");
    printf("\t\t***************************************\n\n");
}

//打开所有的文本文件
void open_allfile() {
    //open_file(file, file_admin);
   //判断存储婚姻信息的文件是否存在,是否能打开
    if ((file = fopen("marriage.txt", "r+")) != NULL) {
        //打开成功
        ;
    }
    else {
        //打开失败
        printf("\t\t          婚姻信息文件打开出错:\n");
        exit(0);
    }

    //判断存储管理员信息的文件是否存在,是否能打开
    if ((file_admin = fopen("admin.txt", "r+")) != NULL) {
        //打开成功
        ;
    }
    else {
        //打开失败
        printf("\t          管理员信息文件打开出错:\n");
        exit(0);
    }

    //判断存储离婚信息的文件是否存在,是否能打开
    if ((file_divorce = fopen("divorce.txt", "r+")) != NULL) {
        //打开成功
        ;
    }
    else {
        //打开失败
        printf("\t          离婚信息文件打开出错:\n");
        exit(0);
    }
}

//后序释放空间
void free_tree(Node** root) {
    if (*root == NULL)
        return;
    free_tree(&((*root)->left));
    free_tree(&((*root)->right));
    free((*root)->info);
    free(*root);
}

void free_other(User** h, Admin** admin) {
    free(*admin);

    User* p = (*h)->next;
    while (p) {
        free(*h);
        *h = p;
        p = p->next;
    }
}

//运行程序操作
void running() {
    //打开所有文件
    open_allfile();

    Admin* admin = readAdmin(file_admin);
    Node* tree = readFile(file);
    divorce = readDivorce(file_divorce);

    admin = login(admin);
    char option[10];
    memu();
    while (1) {
        printf("\n\t\t请输入您的选项:");
        scanf("%s", option);
        printf("\n");
        switch (option[0]) {
            //添加
        case '1':
            tree = add_both(tree);
            break;
        case '2':
            //删除
            tree = del_node(tree);
            break;
        case '3':
            //身份证查询
            printf("\t\t          请输入要查询的身份证号: ");
            char* ID;
            ID = correct_ID();
            searchByID(tree, ID);
            break;
        case '4':
            //查看信息
        {
            int type;
            printf("\t\t          请输入要查看的信息:\n ");
            printf("\t\t          1、已结婚人的信息 \n");
            printf("\t\t          2、已离婚人的信息\n ");
            printf("\t\t          3、所有人的信息 \n");
            printf("\t\t          请输入要查询选项(1-3): ");
            //判断输入的类型
            scanf("%d", &type);
            switch (type)
            {
            case 1:
                display_tree(tree); break;
            case 2:
                display_divorce(); break;
            case 3:
                display_all(tree);
                break;
            default:
                break;
            }
            putchar('\n');
            break;
        }
        case '5':
            //修改婚姻信息
            tree = correct_marriage(tree);
            break;
        case '6':
        {
            printf("\t\t          请输入查询类别:\n");
            printf("\t\t          1、查询结婚人信息:\n");
            printf("\t\t          2、查询离婚人的姓名:\n");
            int type;
            printf("\t\t          请输入要查询的选项(1-2):");
            scanf("%d", &type);
            printf("\t\t          请输入要查询的姓名:");
            char nameToSearch[NameMax];
            scanf("%s", nameToSearch);
            int judge = searchByName(tree, nameToSearch, type);
            if (judge != 1) {
                printf("\t\t查无此人,请检查后再试!\n");
            }
        }
        break;
        case '7':
            //按年龄进行排序
            sort_age(tree);
            break;
        default:
            printf("\t\t无效的选项!\n");
            break;
            break;
        case '9':
            memu();
            break;
        case '8':
            system("cls");
            break;
        case 'a':
            //修改管理员信息
            admin = correct_admin();
            break;
        case 'b':
            system("cls");
            printf("\n\n\t\t\t\t           程序已退出!\n");
            printf("\n\t\t\t\t          欢迎下次使用!\n");
            saveTreeToFile(tree);
            saveDivorceToFile(divorce);
            saveAdminToFile(admin);

            fclose(file);
            fclose(file_divorce);
            fclose(file_admin);

            free_tree(&tree);
            free_other(&divorce, &admin);
            exit(0);
        case 'c':
            saveTreeToFile(tree);
            saveDivorceToFile(divorce);
            saveAdminToFile(admin);
            printf("\t\t          保存成功!\n");
            break;
        }
    }

}

int main() {
    running();
    return 0;
}
 

你可能感兴趣的:(数据结构,c语言,开发语言)