您好,登錄后才能下訂單哦!
這篇文章主要講解了“C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么”吧!
在我們學習完C語言的結構體、指針以及動態(tài)內(nèi)存管理之后,我們就可以實現(xiàn)一些有意思的小項目了,通過這些小項目可以加深我們對于相關知識的理解。
靜態(tài)通訊錄主要要求有
靜態(tài)大小,可以記錄10個人的信息(大小自己定)
記錄的信息如下:名字、性別、年齡、電話、住址
可以實現(xiàn)聯(lián)系人的增刪查改
為了方便代碼的管理和維護,我們分文件實現(xiàn)以上的要求
contact.h 用于聲明相關的接口
contact.c 用于實現(xiàn)相關的接口
test.c 用于測試相關的接口
在contact.h中,我們統(tǒng)一用預處理指令來確定好通訊錄的大小,以及每一個聯(lián)系人信息的范圍大小,方便后續(xù)的修改
在確定好范圍后,我們通過定義結構體類型的方式來實現(xiàn)對數(shù)據(jù)的統(tǒng)一管理
結構體類型確定后,就是相關接口的聲明了
//首先引入需要用到的頭文件 #include<stdio.h> #include<stdlib.h> #include<string.h> //確定每一個聯(lián)系人名字、電話等信息的范圍大小 #define MAX_NAME 10 #define MAX_PHONE 20 #define MAX_ADDR 25 // 確定通訊錄的總大小 #define MAX_CAPACITY 10 //由于每一個聯(lián)系人都有多個信息,因此需要定義一個結構體類型來管理 //定義聯(lián)系人相關信息的結構體 typedef struct PeoInfo { char name[MAX_NAME]; char sex; int age; char phone[MAX_PHONE]; char address[MAX_ADDR]; }peo; //通訊錄內(nèi)包含多個成員,因此也需要統(tǒng)一管理,所以還是使用結構體 //定義一個通訊錄結構體,管理通訊錄和記錄有效聯(lián)系人個數(shù)信息 typedef struct Contact { peo data[MAX_CAPACITY];//這里是一個數(shù)組,數(shù)組的每一個元素都是一個結構體 int size; }con; //------------------------------------------------------ //以下是相關接口的聲明 //菜單接口 void menu(); //對結構體變量進行初始化 void InitContact(con* con); //打印通訊錄信息 void Print(con* con); //實現(xiàn)增加聯(lián)系人的接口 void AddContact(con* con); //實現(xiàn)刪除聯(lián)系人的接口 void DelContact(con* con); //實現(xiàn)查找聯(lián)系人的接口 void SearchContact(con* con); //實現(xiàn)修改聯(lián)系人的接口 void ModifyContact(con* con);
contact.c是整個項目的關鍵,需要對相關接口進行定義
//通訊錄各個接口的實現(xiàn) //首先引入.h文件 #include"Contact.h" //菜單接口 void menu() { printf("*******************************\n"); printf("********靜態(tài)簡易通訊錄*********\n"); printf("******* 0.退出通訊錄 ******\n"); printf("******* 1.增加聯(lián)系人 ******\n"); printf("******* 2.刪除聯(lián)系人 ******\n"); printf("******* 3.查找聯(lián)系人 ******\n"); printf("******* 4.修改聯(lián)系人 ******\n"); printf("******* 5.打印聯(lián)系人 ******\n"); printf("*******************************\n"); printf("\n"); } //對結構體變量進行初始化 void InitContact(con* con) { //結構體的初始化一般用memset //我們首先讓通訊錄結構體變量的數(shù)組一開始為0 memset(con->data, 0, sizeof(con->data)); con->size = 0;//同時由于此時一個聯(lián)系人的信息都沒有,所以size也是0 } //打印通訊錄信息 void Print(con* con){ int i = 0; if (con->size == 0) { printf("暫無可打印信息\n"); return ; } printf("name\tsex\tage\tphone\taddress\n"); for (i = 0; i < con->size; i++) { printf("%s\t%c\t%d\t%s\t%s\n", con->data[i].name, con->data[i].sex, con->data[i].age, con->data[i].phone, con->data[i].address); } } //實現(xiàn)增加聯(lián)系人的接口 void AddContact(con* con) { if (con->size == MAX_CAPACITY) { printf("容量已滿,無法增加\n"); return; } printf("請輸入姓名:\n"); scanf("%s", con->data[con->size].name); getchar(); printf("請選擇性別:(m表示男,w表示女)\n"); scanf("%c", &(con->data[con->size].sex)); printf("請輸入年齡:\n"); scanf("%d", &(con->data[con->size].age)); printf("請輸入手機號碼:\n"); scanf("%s", con->data[con->size].phone); printf("請輸入住址:\n"); scanf("%s", con->data[con->size].address); con->size++; } //實現(xiàn)刪除聯(lián)系人的接口 void DelContact(con* con) { if (con->size == 0) { printf("暫無可以刪除的信息"); return; } printf("請輸入你要刪除的聯(lián)系人的姓名:\n"); char name[MAX_NAME] = {0}; scanf("%s", name); int i = 0; for (i = 0; i < con->size; i++) { if (strcmp(name, (con->data)[i].name) == 0) { int j = 0; for (j = i; j < con->size - 1; j++) { memmove(&(con->data[j]), &(con->data[j + 1]), sizeof(con->data[0])); } con->size--; return; } } printf("你輸入的聯(lián)系人不存在\n"); } //實現(xiàn)查找聯(lián)系人的接口 void SearchContact(con* con) { if (con->size == 0) { printf("暫無查找的信息"); return; } printf("請輸入你要查找的聯(lián)系人的姓名:\n"); char name[MAX_NAME] = { 0 }; scanf("%s", name); int i = 0; for (i = 0; i < con->size; i++) { if (strcmp(name, (con->data)[i].name) == 0) { printf("%s\t%c\t%d\t%s\t%s\n", con->data[i].name, con->data[i].sex, con->data[i].age, con->data[i].phone, con->data[i].address); return; } } printf("你想要查找的聯(lián)系人不存在\n"); } //實現(xiàn)修改聯(lián)系人的接口 void ModifyContact(con* con) { if (con->size == 0) { printf("暫無可以修改的信息"); return; } printf("請輸入你要修改的聯(lián)系人的姓名:\n"); char name[MAX_NAME] = { 0 }; scanf("%s", name); int i = 0; for (i = 0; i < con->size; i++) { if (strcmp(name, (con->data)[i].name) == 0) { printf("請重新輸入姓名:\n"); scanf("%s", con->data[i].name); getchar(); printf("請重新選擇性別:(m表示男,w表示女)\n"); scanf("%c", &(con->data[i].sex)); printf("請重新輸入年齡:\n"); scanf("%d", &(con->data[i].age)); printf("請重新輸入手機號碼:\n"); scanf("%s", con->data[i].phone); printf("請重新輸入住址:\n"); scanf("%s", con->data[i].address); return; } } printf("你想要修改的聯(lián)系人不存在\n"); }
提示
我們在實現(xiàn)接口的時候,如果形參傳入的是指針,一般都需要先判斷一下傳入的指針是否為空指針,以免造成非法訪問,但是由于我的疏忽,就沒有寫上去了!
test.c就是用來測試相關接口的文件,可以根據(jù)自己的想法來設定
#include"Contact.h" int main() { //創(chuàng)建結構體并且初始化 con c; InitContact(&c); menu(); int input = 0; while (1) { printf("請輸入你的選擇:\n"); scanf("%d", &input); switch (input) { case 1: AddContact(&c); break; case 2: DelContact(&c); break; case 3: SearchContact(&c); break; case 4: ModifyContact(&c); break; case 5: Print(&c); break; case 0: printf("退出通訊錄\n"); break; default: printf("你的輸入有誤,請重新選擇\n"); break; } if (input == 0) { break; } } return 0; }
靜態(tài)通訊錄有一個缺點,那就是通訊錄的大小,也就是只能存儲的聯(lián)系人是要求確定大小的,大小給多了浪費空間,給少了又不夠用。
動態(tài)通訊錄就是通過動態(tài)內(nèi)存管理的函數(shù)來實現(xiàn)動態(tài)開辟空間大小,以滿足需要的。
//動態(tài)版本通訊錄的實現(xiàn) #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX_NAME 15 #define MAX_PHONE 15 #define MAX_ADDR 25 //給定通訊錄默認大小為5,不夠可以增容 #define DefaultSize 5 //聯(lián)系人結構體的聲明 typedef struct PeoInfo { char name[MAX_NAME]; char sex; short age; char phone[MAX_PHONE]; char addr[MAX_ADDR]; }peo; //通訊錄結構體的聲明 typedef struct Contact { peo* p;//我們通過指針的方式來管理聯(lián)系人數(shù)組 int capacity; int size; }con; //菜單函數(shù) void menu(); //初始化通訊錄 void InitCon(con* c); //銷毀通訊錄 void DestoryCon(con* c); //檢查容量的接口 void CheckCapacity(con* c); //打印聯(lián)系人信息 void Print(con* c); //聯(lián)系人的增加 void AddCon(con* c); //聯(lián)系人的刪除 void DelCon(con* c); //聯(lián)系人的查找 void SearchCon(con* c); //聯(lián)系人的修改 void ModifyCon(con* c); //------------------------------------------- //下面是我通過快排的原理,手寫的快排來實現(xiàn)一下通過聯(lián)系人名字和年齡排序的接口 //通過名字來排序 void SortByname(con* c); //通過年齡來排序 void SortByage(con* c); void Swap(char* p1, char* p2, int width); void QSort(void* p, int num, int width, int(*cmp)(const void* , const void* )); int cmpbyname(const void* p1,const void* p2); int cmpbyage(const void* p1,const void* p2);
關鍵接口的實現(xiàn)和靜態(tài)通訊錄的大同小異,只不過我們需要多定義一個檢查空間的接口
每次增加聯(lián)系人的時候,就調(diào)用這個接口,做到滿了就增容
其中增容接口使用的時realloc函數(shù)
#include"contact.h" //菜單函數(shù) void menu() { printf("******************************************\n"); printf("************* 動態(tài)版通訊錄 ***********\n"); printf("************* 1.增加聯(lián)系人 ***********\n"); printf("************* 2.刪除聯(lián)系人 ***********\n"); printf("************* 3.查找聯(lián)系人 ***********\n"); printf("************* 4.修改聯(lián)系人 ***********\n"); printf("************* 5.按名字排序 ***********\n"); printf("************* 6.按年齡排序 ***********\n"); printf("************* 7.打印聯(lián)系人 ***********\n"); printf("************* 0.退出通訊錄 ***********\n"); printf("******************************************\n"); } //初始化通訊錄 void InitCon(con* c) { //這里也可以用relloc函數(shù)來初始化,這樣的話就會有初始值 c->p = (con*)malloc(DefaultSize * sizeof(peo)); c->capacity = DefaultSize; c->size = 0; } //銷毀通訊錄 void DestoryCon(con* c) { free(c->p); c->p = NULL; c->capacity = 0; c->size = 0; } //檢查容量的接口 void CheckCapacity(con* c) { if (c->capacity == c->size) { //每次增容二倍 peo* tmp = (peo*)realloc(c->p, 2 * (c->capacity) * sizeof(peo)); if (tmp != NULL) { c->p = tmp; c->capacity = 2 * c->capacity; printf("增容成功\n"); } else { printf("增容失敗\n"); exit(1); } } } //打印聯(lián)系人信息 void Print(con* c) { if (c->size == 0) { printf("暫無可以打印的信息\n"); return; } printf("name\tsex\tage\tphone\taddress\n"); int i = 0; for (i = 0; i < c->size; i++) { printf("%s\t%c\t%d\t%s\t%s\n", c->p[i].name, c->p[i].sex, c->p[i].age, c->p[i].phone, c->p[i].addr); } } //聯(lián)系人的增加 void AddCon(con* c) { //每一次增加聯(lián)系人都要先檢查容量是否足夠 CheckCapacity(c); printf("請輸入名字:>\n"); scanf("%s", c->p[c->size].name); getchar(); printf("請輸入性別:>(m表示男,w表示女)\n"); scanf("%c", &(c->p[c->size].sex)); printf("請輸入年齡:>\n"); scanf("%d", &(c->p[c->size].age)); printf("請輸入電話:>\n"); scanf("%s", c->p[c->size].phone); printf("請輸入地址:>\n"); scanf("%s", c->p[c->size].addr); c->size++; printf("添加成功\n"); } //聯(lián)系人的刪除 void DelCon(con* c) { printf("請輸入你想要刪除的聯(lián)系人的名字\n"); char name[MAX_NAME]; scanf("%s", name); int i = 0; for (i = 0; i < c->size; i++) { if (strcmp(name, c->p[i].name) == 0) { int j = i; for (j = i; j < c->size - 1; j++) { memmove(&(c->p[j]), &(c->p[j + 1]), sizeof(c->p[0])); } c->size--; return; } } printf("你想要刪除的聯(lián)系人不存在\n"); } //聯(lián)系人的查找 void SearchCon(con* c) { printf("請輸入你想要查找的人的名字:\n"); char name[MAX_NAME]; scanf("%s", name); int i = 0; for (i = 0; i < c->size; i++) { if (strcmp(name, c->p[i].name) == 0) { printf("%s\t%c\t%d\t%s\t%s\n", c->p[i].name, c->p[i].sex, c->p[i].age, c->p[i].phone, c->p[i].addr); return; } } printf("你想要查找的聯(lián)系人不存在\n"); } //聯(lián)系人的修改 void ModifyCon(con* c) { printf("請輸入你想要修改的人的名字:\n"); char name[MAX_NAME]; scanf("%s", name); int i = 0; for (i = 0; i < c->size; i++) { if (strcmp(name, c->p[i].name) == 0) { printf("請重新輸入名字:>\n"); scanf("%s", c->p[i].name); getchar(); printf("請重新輸入性別:>(m表示男,w表示女)\n"); scanf("%c", &(c->p[i].sex)); printf("請重新輸入年齡:>\n"); scanf("%d", &(c->p[i].age)); printf("請重新輸入電話:>\n"); scanf("%s", c->p[i].phone); printf("請重新輸入地址:>\n"); scanf("%s", c->p[i].addr); return; } } printf("你想要修改的聯(lián)系人不存在\n"); } //通過名字來排序 void SortByname(con* c) { QSort(c->p, c->size, sizeof(c->p[0]),cmpbyname ); } //通過年齡來排序 void SortByage(con* c) { QSort(c->p, c -> size, sizeof(c->p[0]), cmpbyage); }
這是我根據(jù)快速排序的原理,手寫的快速排序
#include"contact.h" //快排的交換函數(shù) void Swap(char* p1, char* p2, int width) { int i = 0; for (i = 0; i < width; i++) { char tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2++; } } //手寫快排來進行通訊錄排序 void QSort(void* p, int num, int width, int(*cmp)(const void*, const void*)) { int i = 0; for (i = 0; i < num - 1; i++) { int j = 0; for (j = 0; j < num - 1 - i; j++) { if (cmp((char*)p + j * width, (char*)p + (j + 1) * width) > 0) { Swap((char*)p + j * width, (char*)p + (j + 1) * width, width); } } } } int cmpbyage(const void* p1, const void* p2) { return (*(peo*)p1).age - (*(peo*)p2).age; } int cmpbyname(const void* p1, const void* p2) { return strcmp(((peo*)p1)->name,((peo*)p2)->name); }
test.c用于測試相關的接口,可以根據(jù)自己的想法來測試
#include"contact.h" int main() { menu(); int input = 0; con c; InitCon(&c); while (1) { printf("請輸入你的選擇:\n"); scanf("%d", &input); switch (input) { case 1: AddCon(&c); break; case 2: DelCon(&c); break; case 3: SearchCon(&c); break; case 4: ModifyCon(&c); break; case 5: SortByname(&c); break; case 6: SortByage(&c); break; case 7: Print(&c); break; case 0: printf("退出通訊錄\n"); break; } if (input == 0) { DestoryCon(&c); break; } } return 0; }
感謝各位的閱讀,以上就是“C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。