利用結構體實現一個通訊錄

實現一個通訊錄; 通訊錄可以用來存儲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;
}

在擴容過程中,我們經過分析之後,當內存不夠時,考慮到只有添加才需要開闢新的空間。

所以在第一個靜態的版本之上,又加入了動態開闢,這樣當添加不夠時,我們的程序會自動開闢新的空間,爲了當前能夠使用。

在代碼中有註釋,關於開闢的關鍵。

內存中原先保存的位置我們也要管理,否則會造成內存泄漏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章