C語言靜態(tài)與動(dòng)態(tài)通訊錄的實(shí)現(xiàn)流程詳解
本次通訊錄的代碼已經(jīng)放到我的Gitee倉庫中,感興趣的小伙伴可以去看看
靜態(tài)通訊錄
在我們學(xué)習(xí)完C語言的結(jié)構(gòu)體、指針以及動(dòng)態(tài)內(nèi)存管理之后,我們就可以實(shí)現(xiàn)一些有意思的小項(xiàng)目了,通過這些小項(xiàng)目可以加深我們對于相關(guān)知識(shí)的理解。
靜態(tài)通訊錄主要要求有
- 靜態(tài)大小,可以記錄10個(gè)人的信息(大小自己定)
- 記錄的信息如下:名字、性別、年齡、電話、住址
- 可以實(shí)現(xiàn)聯(lián)系人的增刪查改
為了方便代碼的管理和維護(hù),我們分文件實(shí)現(xiàn)以上的要求
- contact.h 用于聲明相關(guān)的接口
- contact.c 用于實(shí)現(xiàn)相關(guān)的接口
- test.c 用于測試相關(guān)的接口
contact.h
在contact.h中,我們統(tǒng)一用預(yù)處理指令來確定好通訊錄的大小,以及每一個(gè)聯(lián)系人信息的范圍大小,方便后續(xù)的修改
在確定好范圍后,我們通過定義結(jié)構(gòu)體類型的方式來實(shí)現(xiàn)對數(shù)據(jù)的統(tǒng)一管理
結(jié)構(gòu)體類型確定后,就是相關(guān)接口的聲明了
//首先引入需要用到的頭文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//確定每一個(gè)聯(lián)系人名字、電話等信息的范圍大小
#define MAX_NAME 10
#define MAX_PHONE 20
#define MAX_ADDR 25
// 確定通訊錄的總大小
#define MAX_CAPACITY 10
//由于每一個(gè)聯(lián)系人都有多個(gè)信息,因此需要定義一個(gè)結(jié)構(gòu)體類型來管理
//定義聯(lián)系人相關(guān)信息的結(jié)構(gòu)體
typedef struct PeoInfo {
char name[MAX_NAME];
char sex;
int age;
char phone[MAX_PHONE];
char address[MAX_ADDR];
}peo;
//通訊錄內(nèi)包含多個(gè)成員,因此也需要統(tǒng)一管理,所以還是使用結(jié)構(gòu)體
//定義一個(gè)通訊錄結(jié)構(gòu)體,管理通訊錄和記錄有效聯(lián)系人個(gè)數(shù)信息
typedef struct Contact {
peo data[MAX_CAPACITY];//這里是一個(gè)數(shù)組,數(shù)組的每一個(gè)元素都是一個(gè)結(jié)構(gòu)體
int size;
}con;
//------------------------------------------------------
//以下是相關(guān)接口的聲明
//菜單接口
void menu();
//對結(jié)構(gòu)體變量進(jìn)行初始化
void InitContact(con* con);
//打印通訊錄信息
void Print(con* con);
//實(shí)現(xiàn)增加聯(lián)系人的接口
void AddContact(con* con);
//實(shí)現(xiàn)刪除聯(lián)系人的接口
void DelContact(con* con);
//實(shí)現(xiàn)查找聯(lián)系人的接口
void SearchContact(con* con);
//實(shí)現(xiàn)修改聯(lián)系人的接口
void ModifyContact(con* con);
contact.c
contact.c是整個(gè)項(xiàng)目的關(guān)鍵,需要對相關(guān)接口進(jìn)行定義
//通訊錄各個(gè)接口的實(shí)現(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");
}
//對結(jié)構(gòu)體變量進(jìn)行初始化
void InitContact(con* con) {
//結(jié)構(gòu)體的初始化一般用memset
//我們首先讓通訊錄結(jié)構(gòu)體變量的數(shù)組一開始為0
memset(con->data, 0, sizeof(con->data));
con->size = 0;//同時(shí)由于此時(shí)一個(gè)聯(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);
}
}
//實(shí)現(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("請輸入手機(jī)號碼:\n");
scanf("%s", con->data[con->size].phone);
printf("請輸入住址:\n");
scanf("%s", con->data[con->size].address);
con->size++;
}
//實(shí)現(xiàn)刪除聯(lián)系人的接口
void DelContact(con* con) {
if (con->size == 0) {
printf("暫無可以刪除的信息");
return;
}
printf("請輸入你要?jiǎng)h除的聯(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");
}
//實(shí)現(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");
}
//實(shí)現(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("請重新輸入手機(jī)號碼:\n");
scanf("%s", con->data[i].phone);
printf("請重新輸入住址:\n");
scanf("%s", con->data[i].address);
return;
}
}
printf("你想要修改的聯(lián)系人不存在\n");
}
提示
我們在實(shí)現(xiàn)接口的時(shí)候,如果形參傳入的是指針,一般都需要先判斷一下傳入的指針是否為空指針,以免造成非法訪問,但是由于我的疏忽,就沒有寫上去了!
test.c
test.c就是用來測試相關(guān)接口的文件,可以根據(jù)自己的想法來設(shè)定
#include"Contact.h"
int main() {
//創(chuàng)建結(jié)構(gòu)體并且初始化
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;
}
動(dòng)態(tài)通訊錄
靜態(tài)通訊錄有一個(gè)缺點(diǎn),那就是通訊錄的大小,也就是只能存儲(chǔ)的聯(lián)系人是要求確定大小的,大小給多了浪費(fèi)空間,給少了又不夠用。
動(dòng)態(tài)通訊錄就是通過動(dòng)態(tài)內(nèi)存管理的函數(shù)來實(shí)現(xiàn)動(dòng)態(tài)開辟空間大小,以滿足需要的。
contact.h
//動(dòng)態(tài)版本通訊錄的實(shí)現(xiàn)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_NAME 15
#define MAX_PHONE 15
#define MAX_ADDR 25
//給定通訊錄默認(rèn)大小為5,不夠可以增容
#define DefaultSize 5
//聯(lián)系人結(jié)構(gòu)體的聲明
typedef struct PeoInfo {
char name[MAX_NAME];
char sex;
short age;
char phone[MAX_PHONE];
char addr[MAX_ADDR];
}peo;
//通訊錄結(jié)構(gòu)體的聲明
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);
//-------------------------------------------
//下面是我通過快排的原理,手寫的快排來實(shí)現(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);
contact.c
關(guān)鍵接口的實(shí)現(xiàn)和靜態(tài)通訊錄的大同小異,只不過我們需要多定義一個(gè)檢查空間的接口
每次增加聯(lián)系人的時(shí)候,就調(diào)用這個(gè)接口,做到滿了就增容
其中增容接口使用的時(shí)realloc函數(shù)
#include"contact.h"
//菜單函數(shù)
void menu() {
printf("******************************************\n");
printf("************* 動(dòng)態(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ù)來初始化,這樣的話就會(huì)有初始值
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("請輸入你想要?jiǎng)h除的聯(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("你想要?jiǎng)h除的聯(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);
}
qsort.c
這是我根據(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++;
}
}
//手寫快排來進(jìn)行通訊錄排序
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
test.c用于測試相關(guān)的接口,可以根據(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;
}
到此這篇關(guān)于C語言靜態(tài)與動(dòng)態(tài)通訊錄的實(shí)現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)C語言 通訊錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言結(jié)構(gòu)體字節(jié)對齊的實(shí)現(xiàn)深入分析
這篇文章主要介紹了C語言結(jié)構(gòu)體字節(jié)對齊的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-10-10
C語言深度解剖篇之關(guān)鍵字以及補(bǔ)充內(nèi)容
C語言的關(guān)鍵字共有32個(gè),根據(jù)關(guān)鍵字的作用,可分其為數(shù)據(jù)類型關(guān)鍵字、控制語句關(guān)鍵字、存儲(chǔ)類型關(guān)鍵字和其它關(guān)鍵字四類,這篇文章主要給大家介紹了關(guān)于C語言深度解剖篇之關(guān)鍵字以及補(bǔ)充內(nèi)容的相關(guān)資料,需要的朋友可以參考下2022-06-06
C++中typedef 及其與struct的結(jié)合使用
這篇文章主要介紹了C++中typedef 及其與struct的結(jié)合使用,需要的朋友可以參考下2014-02-02
opencv3/C++ 使用Tracker實(shí)現(xiàn)簡單目標(biāo)跟蹤
今天小編就為大家分享一篇opencv3/C++ 使用Tracker實(shí)現(xiàn)簡單目標(biāo)跟蹤,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12

