利用结构体实现一个通讯录

实现一个通讯录; 通讯录可以用来存储1000个人的信息,每个人的信息包括: 姓名、性别、年龄、电话、住址

提供方法1.添加联系人信息 2.删除指定联系人信息 3.查找指定联系人信息 4.修改指定联系人信息 5.显示所有联系人信息 6.清空所有联系人 7.以名字排序所有联系人 8. 保存联系人到文件 9. 加载联系人

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define PERSON_INFO_MAX_SIZE 1024
typedef struct PersonInfo{
    char name[1024];
    char phone[1024];
}PersonInfo;

typedef struct AddressBook{//结构体数组
    PersonInfo infos[PERSON_INFO_MAX_SIZE];
    int size;//描述数组中前多少个元素是被使用的,有效元素区间[0,size)
}AddressBook;
//我们将生活中的常识抽象成计算机中的语言

AddressBook g_address_book;

void Init(AddressBook* addr_book){
    assert(addr_book != NULL);
    addr_book-> size = 0;
}

void AddPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("插入一个联系人!\n");
    
    if(addr_book->size >= PERSON_INFO_MAX_SIZE){
        printf("当前通讯已满,插入失败!\n");
        return;
    }
    //每次都把新的联系人放到有效数组的最后一个元素上
    PersonInfo *p = &addr_book->infos[addr_book->size];
    printf("请输入新增的联系人姓名:");
    scanf("%s",p->name);
    printf("请输入新增的联系人的电话:");
    scanf("%s",p->phone);
    //新增完成后,需要更新size
    ++addr_book->size;
    printf("插入联系人成功!\n");
}

void DelPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("删除联系人!\n");
    
    //根据用户输入的下标来删除联系人
    printf("请输入要删除的联系人符号:");
    int id = 0;
    scanf("%d",&id);
    if(id < 0 || id >= addr_book->size){
        printf("您输入的序号有误!删除失败!\n");
        return;
    }
    PersonInfo *p = &addr_book->infos[id];
    printf("您要删除的联系人为[%d] %s,确认请输入Y:",id,p->name);
    char cmd[1024] = {0};
    scanf("%s",cmd);
    if(strcmp(cmd, "Y") != 0){
        printf("删除操作已经取消!\n");
        return;
    }
    PersonInfo* from = &aaddr_book->infos[addr_book->size - 1];
    PersonInfo* to = p;
    *to = *from;
    --addr_book->size;
    printf("删除成功!\n");
}

void ModifyPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("修改联系人\n");
    
    printf("请输入需要修改的联系人序号:");
    int id = 0;
    scanf("%d",&id);
    if(id < 0 || id >= addr_book->size){
        printf("您输入的序号错误");
        return;
    }
    PersonInfo *p = &addr_book->infos[id];
    char input[1024] = {0};
    printf("请输入要修改的姓名:");
    scanf("%s",input);
    if(strcmp(input,"#") != 0){
        strcpy(p->name,input);
    }
    printf("请输入要修改的电话:");
    scanf("%s",input);
    if(strcmp(input,"#") != 0){
        strcpy(p->phone,input);
    }
    printf("修改成功!\n");
}

void FindPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("开始进行查找!\n");
    printf("请输入要查找的姓名:");
    char name[1024] = {0};
    scanf("%s",name);
    int count = 0;
    for(int i = 0;i < addr_book->size;++i){
        PersonInfo* p = &addr_book->infos[i];
        if(strcmp(name,p->name) == 0){
            printf("[%d] %s\t%s\n",i,p->name,p->phone);
        	++count;
        }
    }
    printf("查找完毕!共找到 %d 条记录!\n",count);
}

void SortPersonInfo(AddressBook* addr_book){//只适用于英文名字的排序
    assert(addr_book != NULL);
    int i = 0;
    int j = 0;
    for(i = 0;i < addr_book->size;++i){
        for(j = 0;j < addr_book->size - 1 - i;j++){
            if(strcmp(addr_book->infos[j].name,addr_book->infos[j + 1].name) > 0){
                PersonInfo tmp;
                tmp = addr_book->infos[j];
                addr_book->infos[j] = addr_book->infos[j + 1];
                addr_book->infos[j + 1] = tmp;
            }
        }
    }
}

void PrintAllPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    for(int i = 0;i < addr_book->size;++i){
        PersonInfo* p = &addr_book->infos[i];
        printf("[%d] %s\t%s\n",i ,p->name,p-phone);
    }
}

void ClearPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("清空所有记录!\n");
    printf("您确认要清空所有记录吗?输入 Y 表示确定");
    char cmd[1024] = {0};
    scanf("%s",&cmd);
    if(strcmp(cmd,"Y") != 0){
        printf("清空操作取消");
        return;
    }
    addr_book->size = 0;
    printf("清空操作成功!\n");
}

int Menu(){
    printf("=================");
    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("=================");
    int choice = 0;
    scanf("%d",&choice);
    return choice;
}

int main(){
    //1.对通讯录进行初始化
    Init(&g_address_book);
    typedef void(*pfunc_t)(AddressBook*);
    pfunc_t table[] = {
        AddPersonInfo,
        DelPersonInfo,
        ModifyPersonInfo,
        FindPersonInfo,
        SortPersonInfo,
        PrintAllPersonInfo,
        ClearPersonInfo
    }
    while(1){
        int choice = Menu();
        if(choice < 0 || choice > (int)(sizeof(table) / sizeof(table[0]))){
            printf("您的输入有误!\n")
        }
        if(choice == 0){
            printf("goodbye!\n");
            break;
        }
        table[choice - 1](&g_address_book);
    }
    return 0;
}

这个通讯录只是一个静态的,此时还可以进行一些改版,将其变为动态结合的,这时候可利用到malloc函数

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define PERSON_INFO_MAX_SIZE 1024
typedef struct PersonInfo{
    char name[1024];
    char phone[1024];
}PersonInfo;

typedef struct AddressBook{//结构体数组
    PersonInfo* infos;
    int capacity;//容量,infos指针指向的动态数组的长度(元素个数)
    int size;//描述数组中前多少个元素是被使用的,有效元素区间[0,size)
}AddressBook;
//我们将生活中的常识抽象成计算机中的语言

AddressBook g_address_book;

void Init(AddressBook* addr_book){
    assert(addr_book != NULL);
    addr_book-> size = 0;
    addr_book->capacity = 10;
    addr_book->infos = (PersonInfo*)malloc(sizeof(PersonInfo) * addr_book->capacity);
    
}
void Realloc(AddressBook* addr_book){
    assert(addr_book != NULL);
    //此处每次扩容多少,这样的策略完全是我们自定制的
    //1.扩大capacity的取值
    addr_book->capacity *= 2;
    //2.申请一个更大的内存
    PersonInfo* old_infos = addr_book->infos;    
    addr_book->infos = (PersonInfo*)malloc(addr_book->capacity * sizeof(PersonInfo));
    //3.把原有的内存中的数据复制过来
    for(int i = 0;i < addr_book->size;++i){
        addr_book->infos[i] = old_infos[i];
    }
    //4.释放原有的内存
    free(old_infos);
}
void AddPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("插入一个联系人!\n");
    
    if(addr_book->size >= addr_book->capacity){
        printf("当前通讯已满,插入失败!进行扩容!\n");
        Realloc(addr_book);
    }
    //每次都把新的联系人放到有效数组的最后一个元素上
    PersonInfo *p = &addr_book->infos[addr_book->size];
    printf("请输入新增的联系人姓名:");
    scanf("%s",p->name);
    printf("请输入新增的联系人的电话:");
    scanf("%s",p->phone);
    //新增完成后,需要更新size
    ++addr_book->size;
    printf("插入联系人成功!\n");
}

void DelPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("删除联系人!\n");
    
    //根据用户输入的下标来删除联系人
    printf("请输入要删除的联系人符号:");
    int id = 0;
    scanf("%d",&id);
    if(id < 0 || id >= addr_book->size){
        printf("您输入的序号有误!删除失败!\n");
        return;
    }
    PersonInfo *p = &addr_book->infos[id];
    printf("您要删除的联系人为[%d] %s,确认请输入Y:",id,p->name);
    char cmd[1024] = {0};
    scanf("%s",cmd);
    if(strcmp(cmd, "Y") != 0){
        printf("删除操作已经取消!\n");
        return;
    }
    PersonInfo* from = &aaddr_book->infos[addr_book->size - 1];
    PersonInfo* to = p;
    *to = *from;
    --addr_book->size;
    printf("删除成功!\n");
}

void ModifyPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("修改联系人\n");
    
    printf("请输入需要修改的联系人序号:");
    int id = 0;
    scanf("%d",&id);
    if(id < 0 || id >= addr_book->size){
        printf("您输入的序号错误");
        return;
    }
    PersonInfo *p = &addr_book->infos[id];
    char input[1024] = {0};
    printf("请输入要修改的姓名:");
    scanf("%s",input);
    if(strcmp(input,"#") != 0){
        strcpy(p->name,input);
    }
    printf("请输入要修改的电话:");
    scanf("%s",input);
    if(strcmp(input,"#") != 0){
        strcpy(p->phone,input);
    }
    printf("修改成功!\n");
}

void FindPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("开始进行查找!\n");
    printf("请输入要查找的姓名:");
    char name[1024] = {0};
    scanf("%s",name);
    int count = 0;
    for(int i = 0;i < addr_book->size;++i){
        PersonInfo* p = &addr_book->infos[i];
        if(strcmp(name,p->name) == 0){
            printf("[%d] %s\t%s\n",i,p->name,p->phone);
        	++count;
        }
    }
    printf("查找完毕!共找到 %d 条记录!\n",count);
}

void SortPersonInfo(AddressBook* addr_book){//只适用于英文名字的排序
    assert(addr_book != NULL);
    int i = 0;
    int j = 0;
    for(i = 0;i < addr_book->size;++i){
        for(j = 0;j < addr_book->size - 1 - i;j++){
            if(strcmp(addr_book->infos[j].name,addr_book->infos[j + 1].name) > 0){
                PersonInfo tmp;
                tmp = addr_book->infos[j];
                addr_book->infos[j] = addr_book->infos[j + 1];
                addr_book->infos[j + 1] = tmp;
            }
        }
    }
}

void PrintAllPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    for(int i = 0;i < addr_book->size;++i){
        PersonInfo* p = &addr_book->infos[i];
        printf("[%d] %s\t%s\n",i ,p->name,p-phone);
    }
}

void ClearPersonInfo(AddressBook* addr_book){
    assert(addr_book != NULL);
    printf("清空所有记录!\n");
    printf("您确认要清空所有记录吗?输入 Y 表示确定");
    char cmd[1024] = {0};
    scanf("%s",&cmd);
    if(strcmp(cmd,"Y") != 0){
        printf("清空操作取消");
        return;
    }
    addr_book->size = 0;
    printf("清空操作成功!\n");
}

int Menu(){
    printf("=================");
    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("=================");
    int choice = 0;
    scanf("%d",&choice);
    return choice;
}

int main(){
    //1.对通讯录进行初始化
    Init(&g_address_book);
    typedef void(*pfunc_t)(AddressBook*);
    pfunc_t table[] = {
        AddPersonInfo,
        DelPersonInfo,
        ModifyPersonInfo,
        FindPersonInfo,
        SortPersonInfo,
        PrintAllPersonInfo,
        ClearPersonInfo
    }
    while(1){
        int choice = Menu();
        if(choice < 0 || choice > (int)(sizeof(table) / sizeof(table[0]))){
            printf("您的输入有误!\n")
        }
        if(choice == 0){
            printf("goodbye!\n");
            break;
        }
        table[choice - 1](&g_address_book);
    }
    return 0;
}

在扩容过程中,我们经过分析之后,当内存不够时,考虑到只有添加才需要开辟新的空间。

所以在第一个静态的版本之上,又加入了动态开辟,这样当添加不够时,我们的程序会自动开辟新的空间,为了当前能够使用。

在代码中有注释,关于开辟的关键。

内存中原先保存的位置我们也要管理,否则会造成内存泄漏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值