1. 项目总结

使用函数指针数组构建转移表,使得不同功能函数的调用不用拘泥于一连串的if else,而只需要一个数组元素的下标引用就能完成。

// 定义转移表类型
typedef void(*p_fun)();

// 定义转移表
p_fun arr[] = {
    add_person,
    remove_person,
    update_person,
    find_person,
    print_all_person,
    clear_addressbook,
    save_file,
};

// 转移表调用
arr[choice]();

2. AddressBook.h

#define _CRT_SECURE_NO_WARNINGS
#pragma once

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <Windows.h>

// 通讯录的每个条目的抽象
typedef struct Person {
    char name[1024];
    char phone_number[1024];
}Person;

// 通讯录本体的抽象
typedef struct AddressBook {
    Person* arr;
    int size;
    int capacity;
}AddressBook;

// 定义全局变量通讯录
AddressBook g_address_book;

// 定义转移表类型
typedef void(*p_fun)();

void Init(int capacity);
void add_person();
void remove_person();
void update_person();
void find_person();
void print_all_person();
void clear_addressbook();
void save_file();
void Test();
int Menu();

3. AddressBook.c

#include "AddressBook.h"

void Init(int capacity) {
    Person* tmp;
    tmp = (Person *)malloc(sizeof(Person) * capacity);
    if (tmp == NULL) {
        assert(0);
        return;
    }

    g_address_book.arr = tmp;
    g_address_book.size = 0;
    g_address_book.capacity = capacity;
}

// 检查通讯录是否已满
void checkCapacity() {
    if (g_address_book.size >= g_address_book.capacity) {
        int newCapacity = g_address_book.capacity * 2;
        Person* tmp = (Person *)realloc(g_address_book.arr, sizeof(Person) * newCapacity);
        if (tmp == NULL) {
            assert(0);
            return;
        }

        g_address_book.arr = tmp;
        g_address_book.capacity = newCapacity;
    }
}

// 1. 增加联系人
void add_person() {
    checkCapacity();

    printf("请输入新增联系人姓名:");
    char name[1024] = { 0 };
    scanf("%s", name);

    printf("请输入新增联系人电话:");
    char phone_number[1024] = { 0 };
    scanf("%s", phone_number);

    // 插入排序
    int index = g_address_book.size;
    while (index > 0 && strcmp(g_address_book.arr[index - 1].name, name) > 0) {
        g_address_book.arr[index] = g_address_book.arr[index - 1];
        index--;
    }
    strcpy(g_address_book.arr[index].name, name);
    strcpy(g_address_book.arr[index].phone_number, phone_number);
    g_address_book.size++;

    printf("增加联系人成功\n");
    system("pause");
    system("cls");
}

// 2. 删除联系人
void remove_person() {
    if (g_address_book.size == 0) {
        printf("通讯录为空,不能删除联系人!\n");
        system("pause");
        system("cls");
        return;
    }

    int index = -1;
    printf("请输入要删除的联系人编号:");
    scanf("%d", &index);

    // 输入有效性判定
    if (index < 0 || index >= g_address_book.size) {
        printf("输入的编号非法,请退出!\n");
        system("pause");
        system("cls");
        return;
    }

    // 删除元素
    while (index < g_address_book.size - 1) {
        g_address_book.arr[index] = g_address_book.arr[index + 1];
        index++;
    }
    g_address_book.size--;

    printf("删除条目成功!\n");
    system("pause");
    system("cls");
}

// 3. 修改联系人
void update_person() {
    if (g_address_book.size == 0) {
        printf("通讯录为空,不能修改联系人!\n");
        system("pause");
        system("cls");
        return;
    }

    int index = -1;
    printf("请输入要修改的联系人编号:");
    scanf("%d", &index);

    // 输入有效性判定
    if (index < 0 || index >= g_address_book.size) {
        printf("输入的编号非法,请退出!\n");
        system("pause");
        system("cls");
        return;
    }

    // 修改
    printf("请输入新的联系人姓名(%s):", g_address_book.arr[index].name);
    char name[1024] = { 0 };
    scanf("%s", name);

    printf("请输入新的联系人电话(%s):", g_address_book.arr[index].phone_number);
    char phone_number[1024] = { 0 };
    scanf("%s", phone_number);

    strcpy(g_address_book.arr[index].name, name);
    strcpy(g_address_book.arr[index].phone_number, phone_number);

    printf("修改联系人成功!\n");
    system("pause");
    system("cls");
}

// 4. 查找联系人
void find_person() {
    printf("请输入要查找的联系人的姓名:");
    char name[1024] = { 0 };
    scanf("%s", name);

    int index = 0;
    int count = 0;
    while (index < g_address_book.size) {
        if (strcmp(name, g_address_book.arr[index].name) == 0) {
            printf("[ %2d ] ", index);
            printf("%7s", g_address_book.arr[index].name);
            printf("%10s\n", g_address_book.arr[index].phone_number);
            count++;
        }
        index++;
    }
    printf("共找到了%d条结果\n", count);
    system("pause");
    system("cls");
}

// 5. 输出全部联系人
void print_all_person() {
    int index = 0;

    while (index < g_address_book.size) {
        printf("[ %2d ] ", index);
        printf("%7s", g_address_book.arr[index].name);
        printf("%15s\n", g_address_book.arr[index].phone_number);
        index++;
    }
    printf("共打印了%d条条目\n", g_address_book.size);
    system("pause");
    system("cls");
}

// 6. 清空通讯录
void clear_addressbook() {
    g_address_book.size = 0;
    printf("清空通讯录成功!\n");
    system("pause");
    system("cls");
}

// 7. 保存通讯录到文件
void save_file() {
    FILE* pFile;
    pFile = fopen("AddressBook.txt", "w");

    if (pFile != NULL) {
        int index = 0;
        while (index < g_address_book.size) {
            fprintf(pFile, "[ %2d ] %7s%15s\n", index, g_address_book.arr[index].name,
                g_address_book.arr[index].phone_number);
            index++;
        }

        fclose(pFile);
        printf("通讯录写入文件成功,文件名AddressBook.txt\n");
    }
    else {
        printf("文件打开失败!\n");
    }

    system("pause");
    system("cls");
}

int Menu() {
    printf("--------------------------------\n");
    printf("         1. 增加联系人           \n");
    printf("         2. 删除联系人           \n");
    printf("         3. 更新联系人           \n");
    printf("         4. 查找联系人           \n");
    printf("         5. 打印通讯录           \n");
    printf("         6. 清空通讯录           \n");
    printf("         7. 保存通讯录到文件     \n");
    printf("         0. 退出                \n");
    printf("--------------------------------\n");
    printf("请输入你的选择:");
    int choice = -1;
    scanf("%d", &choice);

    return choice;
}

// 测试
void Test() {
    Init(3);

    // 定义转移表
    p_fun arr[] = {
        add_person,
        remove_person,
        update_person,
        find_person,
        print_all_person,
        clear_addressbook,
        save_file,
    };

    while (1) {
        int choice = Menu();
        if (choice < 0 || choice > 8) {
            printf("输入有误,请重新输入\n");
            system("pause");
            system("cls");
            continue;
        }
        else if (choice == 0) {
            exit(0);
        }
        else {
            Sleep(200);
            system("cls");
            arr[choice - 1]();
        }
    }
}

4. Main.c

#include "AddressBook.h"

int main() {
    Test();

    system("pause");
    return 0;
}
Last modification:November 10th, 2019 at 10:08 am