C語言實現一個文件版動態通訊錄流程詳解
通訊錄思維導圖
一、Contact.h
#include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #define NAME_MAX 20 #define SEX_MAX 5 #define TELE_MAX 11 #define ADDR_MAX 30 #define INIT_CAPA 3 #define INC_CAPA 2 typedef struct PeoInfo { char name[NAME_MAX]; int age; char sex[SEX_MAX]; char tele[TELE_MAX]; char addr[ADDR_MAX]; }PeoInfo; //動態版本 typedef struct Contact { PeoInfo* data; int sz;//表示通訊錄有多少個聯系人 int capacity;//表示通訊錄的最大容量 }Contact; //初始化通訊錄 void InitContact(Contact* pc); //添加聯系人 void AddContact(Contact* pc); //刪除聯系人 void DelContact(Contact* pc); //顯示通訊錄 void ShowContact(const Contact* pc); //查找聯系人 void SearchContact(Contact*pc); //修改聯系人' void ModifyContact(Contact*pc); //通過名字排序聯系人 void ByNameSortContact(Contact* pc); //銷毀聯系人 void DestroyContact(Contact* pc); //保存聯系人到文本文件中 void SaveContact(Contact* pc); //從文件中讀取聯系人的信息 void GetContact(Contact* pc);
這些是頭文件的包含,函數的聲明,以及#define定義的常量,為瞭以後修改方便
二、Contact.c
1.初始化通訊錄
void InitContact(Contact* pc)//初始化通訊錄 { assert(pc!=NULL); pc-> sz = 0; pc->capacity = INIT_CAPA; PeoInfo * ptr = (PeoInfo*)calloc(INIT_CAPA, sizeof(PeoInfo)); if (ptr == NULL) { perror("InitContact"); return; } pc->data = ptr; GetContact(pc); }
初始化通訊錄的容量開始為3,sz初始時為0,動態開辟的ptr開辟成功在賦給data。
2.檢查容量是否滿
void check_capacity(Contact* pc)//檢查容量是否滿 { assert(pc); if (pc->capacity == pc->sz) { PeoInfo*ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo)); if (ptr == NULL) { perror("check_capacity"); return; } pc->data = ptr; pc->capacity += INC_CAPA; printf("增容成功\n"); } }
如果容量滿,則每次增容兩個,如果想要增容更多,則修改define定義的常量就可以修改瞭。
realloc開辟的時候有可能是用pc->data來往後擴大增容,也有可能是用新的空間來開辟,為瞭防止開辟失敗,使原有的數據丟失,則先使用新的指針變量來接收動態開辟的空間,如果開辟成功,再將它賦給data。
3.添加聯系人
void AddContact(Contact* pc)//添加聯系人 { assert(pc != NULL); check_capacity(pc); printf("請輸入姓名:\n"); scanf("%s", pc->data[pc->sz].name); printf("請輸入年齡:\n"); scanf("%d", &(pc->data[pc->sz].age)); printf("請輸入性別:\n"); scanf("%s", pc->data[pc->sz].sex); printf("請輸入號碼:\n"); scanf("%s", pc->data[pc->sz].tele); printf("請輸入地址:\n"); scanf("%s", pc->data[pc->sz].addr); printf("添加聯系人成功\n"); pc->sz++; }
添加聯系人前,需要先判斷是否需要增容
4.顯示聯系人
void ShowContact(const Contact* pc)//顯示聯系人 { assert(pc != NULL); printf("%-20s\t%-4s\t%-4s\t%-12s\t%-30s\n","姓名","年齡","性別","電話號碼","地址"); for (int i = 0; i < pc->sz; i++) { printf("%-20s\t%-4d\t%-4s\t%-12s\t%-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } }
5.查找聯系人
int ByNameFind(Contact* pc, char name[])//通過名字查找聯系人 { for (int i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; } void SearchContact(Contact* pc)//查找聯系人 { assert(pc); char name[NAME_MAX]; printf("請輸入要查找的聯系人\n"); scanf("%s", name); int ret = ByNameFind(pc, name); if (ret == -1) { printf("查無此人\n"); return; } printf("%-20s\t%-4s\t%-4s\t%-12s\t%-30s\n", "姓名", "年齡", "性別", "電話號碼", "地址"); printf("%-20s\t%-4d\t%-4s\t%-12s\t%-30s\n", pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr); }
註意:名字屬於字符串,名字的比較需要用strcmp來比較,如果返回-1,則是沒有找到聯系人,如果找到瞭,則就打印這個聯系人的信息出來
6.修改聯系人
void ModifyContact(Contact* pc)//修改聯系人 { assert(pc); char name[NAME_MAX]; printf("請輸入要修改的聯系人姓名\n"); scanf("%s", name); int pos = ByNameFind(pc, name); if (pos == -1) { printf("找不到該聯系人\n"); return; } printf("請輸入姓名:\n"); scanf("%s", pc->data[pos].name); printf("請輸入年齡:\n"); scanf("%d", &(pc->data[pos].age)); printf("請輸入性別:\n"); scanf("%s", pc->data[pos].sex); printf("請輸入號碼:\n"); scanf("%s", pc->data[pos].tele); printf("請輸入地址:\n"); scanf("%s", pc->data[pos].addr); printf("修改聯系人成功\n"); }
註意:想要修改這個聯系人,也需要通訊錄中有這個聯系人,所以要先查找到這個聯系人,所以調用封裝好的通過名字查找聯系人這個函數就可以瞭,如果返回-1,則就是沒有該聯系人,無法修改,如果找到瞭,則才能夠修改此聯系人的信息。
7.通過名字來排序聯系人
void ByNameSortContact(Contact* pc)//通過名字來排序 { assert(pc); if (pc->sz == 0) { printf("無聯系人,無法排序\n"); return; } PeoInfo temp; for (int i = 0; i < pc->sz - 1; i++) { for(int j = 0 ;j<pc->sz-1-i;j++) { if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0) { temp = pc->data[j]; pc->data[j] = pc->data[j + 1]; pc->data[j + 1] = temp; } } } printf("排序成功\n"); }
註意:這裡通過名字來排序聯系人,也是需要用到strcmp這個庫函數的,strcmp是一個字符來比較的,如果有一個字符大的話就要進行交換,利用的是冒泡排序思想來排序聯系人的
8.保存聯系人到文本文件中
void SaveContact(Contact* pc) { assert(pc); FILE* pf = fopen("Contact.txt", "wb"); if (pf == NULL) { perror("fopen"); } else { for (int i = 0; i < pc->sz; i++) { fwrite(pc->data + i, sizeof(PeoInfo), 1, pf); } fclose(pf); pf = NULL; printf("保存數據成功\n"); } }
註意:FILE是C語言標準的指針,wb是用二進制的方式寫入文本文件中,而fwrite的用法我們可以利用cplusplus來查找它的用法,裡面介紹瞭它的每個參數的用法,第一個參數ptr其實就是傳我們的data的指針進去,第二個參數本質就是求大小的,求得是PeoInfo得大小,第三個參數就是每次添加幾個聯系人,每次添加1個。第四個參數是把文件流放入
9.從文件中讀取聯系人的信息
//從文件中初始化聯系人 void GetContact(Contact* pc) { assert(pc); FILE* pf = fopen("Contact.txt", "rb"); if (pf == NULL) { perror("GetContact::fopen"); } else { PeoInfo ptr = { 0 }; int i = 0; while (fread(&ptr, sizeof(PeoInfo), 1, pf)) { check_capacity(pc); pc->data[i] = ptr; i++; pc->sz++; } fclose(pf); pf = NULL; } }
註意:rb是利用二進制來讀取聯系人的,fread的用法如上圖所示。
10.銷毀聯系人
//銷毀聯系人 void DestroyContact(Contact* pc) { free(pc->data); pc->data = NULL; pc->capacity = 0; pc->sz = 0; }
註意:在我們退出通訊錄時,要將它進行銷毀
三、text.c
#include"Contact.h" void menu() { printf("**********************************\n"); printf("*******1.Add 2.Del ********\n"); printf("*******3.Search 4.Modify********\n"); printf("*******5.Show 6.Sort ********\n"); printf("*******0.exit ********\n"); printf("**********************************\n"); } enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT }; int main() { Contact con; InitContact(&con); int input = 0; do { menu(); printf("請輸入數字:\n"); scanf("%d", &input); switch (input) { case ADD: AddContact(&con); break; case DEL : DelContact(&con); break; case SEARCH: SearchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case SORT: ByNameSortContact(&con); break; case EXIT: SaveContact(&con); DestroyContact(&con); printf("退出程序\n"); break; default: printf("輸入錯誤,請重新輸入\n"); break; } } while (input); return 0;
註意:首先要建立菜單,然後用枚舉來定義case後面,這樣為瞭可以讓我們看代碼更清晰,在運行程序時要將聯系人從文件中讀取出來,在退出文件時,要把聯系人保存到文本文件中去,在進行銷毀。
好瞭,小編的分享到這裡就結束瞭,如果有什麼不足的地方請大佬多多指教!!!
到此這篇關於C語言實現一個文件版動態通訊錄流程詳解的文章就介紹到這瞭,更多相關C語言動態通訊錄內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!