大家好,我是蘇貝,本篇博客帶大家優(yōu)化上一篇的通訊錄,如果你覺(jué)得我寫的還不錯(cuò)的話,可以給我一個(gè)贊??嗎,感謝??
一. 前言
在上一篇博文 實(shí)現(xiàn)通訊錄管理系統(tǒng) 的最后,我們了解了那段代碼的問(wèn)題:通訊錄的大小是固定的100個(gè)元素,如果想要存放1000個(gè)人的信息,那么空間就不夠了;如果信息太少,只想存10個(gè)人的信息,那么空間就大了。即使可以在源代碼中修改#define定義的值解決,也不免有些麻煩。怎么解決?用動(dòng)態(tài)內(nèi)存管理!
本篇博文要實(shí)現(xiàn)通訊錄管理系統(tǒng),假設(shè)初始時(shí)只能存儲(chǔ)3個(gè)人的信息,若超過(guò)三人,則通訊錄容量+2,再存儲(chǔ)聯(lián)系人信息
二. 動(dòng)態(tài)通訊錄
我們從test.c文件中往下看,明白要修改的代碼
2.1 通訊錄結(jié)構(gòu)體
在test.c文件中,我們先定義了通訊錄變量。那么,通訊錄類型是否需要修改呢?人的信息的結(jié)構(gòu)體類型自然是不用修改的
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char gender[GENDER_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
但是通訊錄類型似乎需要修改。因?yàn)殪o態(tài)版本中規(guī)定了通訊錄最大存儲(chǔ)100個(gè)人的信息,而我們的優(yōu)化是用malloc函數(shù)和realloc函數(shù)實(shí)現(xiàn)動(dòng)態(tài)管理通訊錄,所以從靜態(tài)版本的data數(shù)組到動(dòng)態(tài)版本的data指針,指向之后用malloc函數(shù)開(kāi)辟的空間。除了要知道當(dāng)前通訊錄中存放的人的信息的個(gè)數(shù),我們也要知道通訊錄的容量。當(dāng)存放的人的信息的個(gè)數(shù)==通訊錄的容量時(shí),我們就應(yīng)該要增加容量了
//靜態(tài)版本
//typedef struct Contact
//{
// PeoInfo data[MAX];
// int sz;
//}Contact;
//動(dòng)態(tài)版本
typedef struct Contact
{
PeoInfo *data;
int sz;//當(dāng)前通訊錄中存放的人的信息的個(gè)數(shù)
int capacity;//通訊錄的容量
}Contact;
2.2 初始化通訊錄
靜態(tài)初始化時(shí),是將sz的值賦值為0,再將data數(shù)組中的內(nèi)容全部初始化為0。動(dòng)態(tài)初始化時(shí),sz也要被賦值為0,通訊錄容量capacity要被賦值為3,3是#define定義的標(biāo)識(shí)符常量。將malloc函數(shù)或者calloc函數(shù)開(kāi)辟的空間的起始位置的地址傳給指針變量data,因?yàn)樾枰獙㈤_(kāi)辟的空間全初始化為0,所以使用calloc函數(shù)。最后要判斷空間是否開(kāi)辟成功,如果不成功就會(huì)返回NULL,所以要對(duì)指針變量data判斷
//靜態(tài)初始化通訊錄
//void InitContact(Contact* pc)
//{
// assert(pc);
// pc->sz = 0;
// memset(pc->data, 0, sizeof(pc->data));
//}
//動(dòng)態(tài)初始化通訊錄
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = DEFAULT_CAP;//3
pc->data = (PeoInfo*)calloc(pc->capacity, sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact_calloc");
return;
}
}
2.3 增加聯(lián)系人
靜態(tài)通訊錄中,增加聯(lián)系人時(shí)要先判斷通訊錄是否滿了,那我們動(dòng)態(tài)通訊錄中,也需要判斷通訊錄是否滿了,如果滿了,那就要增加通訊錄的容量。用realloc函數(shù)修改開(kāi)辟的內(nèi)存空間的大小,每次增容時(shí),容量增加2,2是#define定義的標(biāo)識(shí)符常量。判斷增容是否成功,如果指針變量tmp是NULL,開(kāi)辟失敗。如果不是,那將變量tmp賦值給指針變量data
//靜態(tài)增加聯(lián)系人
//void AddContact(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通訊錄已滿,增加失敗\n");
// return;
// }
// printf("請(qǐng)輸入名字:");
// scanf("%s",pc->data[pc->sz].name );
// printf("請(qǐng)輸入年齡:");
// scanf("%d", &(pc->data[pc->sz].age));
// printf("請(qǐng)輸入性別:");
// scanf("%s", pc->data[pc->sz].gender);
// printf("請(qǐng)輸入電話:");
// scanf("%s", pc->data[pc->sz].tele);
// printf("請(qǐng)輸入地址:");
// scanf("%s", pc->data[pc->sz].addr);
//
// pc->sz++;
// printf("增加成功\n");
//}
//動(dòng)態(tài)增加聯(lián)系人
void AddContact(Contact* pc)
{
assert(pc);
//增容
if (pc->sz == pc->capacity)
{
PeoInfo* tmp = realloc(pc->data, (pc->capacity + DEFAAULT_INI) * sizeof(PeoInfo));
if (tmp == NULL)
{
perror("AddContact_realloc");
return;
}
pc->data = tmp;
pc->capacity += DEFAAULT_INI;
printf("增容成功\n");
}
printf("請(qǐng)輸入名字:");
scanf("%s", pc->data[pc->sz].name);
printf("請(qǐng)輸入年齡:");
scanf("%d", &(pc->data[pc->sz].age));
printf("請(qǐng)輸入性別:");
scanf("%s", pc->data[pc->sz].gender);
printf("請(qǐng)輸入電話:");
scanf("%s", pc->data[pc->sz].tele);
printf("請(qǐng)輸入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
2.4 銷毀通訊錄
因?yàn)槭褂昧藙?dòng)態(tài)內(nèi)存開(kāi)辟空間,所以最好在退出程序前釋放掉所開(kāi)辟的空間
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
}
三. 模塊化代碼實(shí)現(xiàn)
3.1 test.c
#include"contact.h"
void menu()
{
printf("-----------------------------------\n");
printf("***********************************\n");
printf("****** 1.Add 2.Del ******\n");
printf("****** 3.Select 4.Modify ******\n");
printf("****** 5.Show 6.sort ******\n");
printf("****** 0.exit ******\n");
printf("***********************************\n");
printf("-----------------------------------\n");
}
enum Option
{
EXIT,
ADD,
DEL,
SELECT,
MODIFY,
SHOW,
SORT
};
int main()
{
Contact con;
//初始化通訊錄
InitContact(&con);
int input = 0;
do
{
menu();
printf("請(qǐng)選擇:");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SELECT:
SelectContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SHOW:
ShowContact(&con);
break;
case SORT:
SortContact(&con);
break;
case EXIT:
printf("退出程序\n");
DestroyContact(&con);
break;
default:
printf("選擇錯(cuò)誤,請(qǐng)重新選擇\n");
break;
}
} while (input);
return 0;
}
3.2 contact.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define NAME_MAX 20
#define GENDER_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
//#define MAX 1000
#define DEFAULT_CAP 3
#define DEFAAULT_INI 2
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char gender[GENDER_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//靜態(tài)版本
//typedef struct Contact
//{
// PeoInfo data[MAX];
// int sz;
//}Contact;
//動(dòng)態(tài)版本
typedef struct Contact
{
PeoInfo *data;
int sz;//當(dāng)前通訊錄中存放的人的信息的個(gè)數(shù)
int capacity;//通訊錄的容量
}Contact;
//初始化通訊錄
void InitContact(Contact* pc);
//增加聯(lián)系人
void AddContact(Contact* pc);
//刪除聯(lián)系人
void DelContact(Contact* pc);
//打印通訊錄
void ShowContact(Contact* pc);
//查找聯(lián)系人
void SelectContact(Contact* pc);
//修改聯(lián)系人信息
void ModifyContact(Contact* pc);
//以名字排序所有聯(lián)系人
void SortContact(Contact* pc);
//銷毀通訊錄
void DestroyContact(Contact* pc);
3.3 contact.c
#include"contact.h"
//靜態(tài)初始化通訊錄
//void InitContact(Contact* pc)
//{
// assert(pc);
// pc->sz = 0;
// memset(pc->data, 0, sizeof(pc->data));
//}
//動(dòng)態(tài)初始化通訊錄
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = DEFAULT_CAP;
pc->data = (PeoInfo*)calloc(pc->capacity, sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact_calloc");
return;
}
}
//靜態(tài)增加聯(lián)系人
//void AddContact(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通訊錄已滿,增加失敗\n");
// return;
// }
// printf("請(qǐng)輸入名字:");
// scanf("%s",pc->data[pc->sz].name );
// printf("請(qǐng)輸入年齡:");
// scanf("%d", &(pc->data[pc->sz].age));
// printf("請(qǐng)輸入性別:");
// scanf("%s", pc->data[pc->sz].gender);
// printf("請(qǐng)輸入電話:");
// scanf("%s", pc->data[pc->sz].tele);
// printf("請(qǐng)輸入地址:");
// scanf("%s", pc->data[pc->sz].addr);
//
// pc->sz++;
// printf("增加成功\n");
//}
//動(dòng)態(tài)增加聯(lián)系人
void AddContact(Contact* pc)
{
assert(pc);
//增容
if (pc->sz == pc->capacity)
{
PeoInfo* tmp = realloc(pc->data, (pc->capacity + DEFAAULT_INI) * sizeof(PeoInfo));
if (tmp == NULL)
{
perror("AddContact_realloc");
return;
}
pc->data = tmp;
pc->capacity += DEFAAULT_INI;
printf("增容成功\n");
}
printf("請(qǐng)輸入名字:");
scanf("%s", pc->data[pc->sz].name);
printf("請(qǐng)輸入年齡:");
scanf("%d", &(pc->data[pc->sz].age));
printf("請(qǐng)輸入性別:");
scanf("%s", pc->data[pc->sz].gender);
printf("請(qǐng)輸入電話:");
scanf("%s", pc->data[pc->sz].tele);
printf("請(qǐng)輸入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
int FindOfName(char* name, Contact* pc)
{
assert(name && pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(name, (pc->data[i].name)))
return i;
}
return -1;
}
//刪除聯(lián)系人
void DelContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
if (pc->sz == 0)
{
printf("通訊錄為空,刪除失敗\n");
return;
}
printf("請(qǐng)輸入要?jiǎng)h除的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要?jiǎng)h除的人\n");
return;
}
int i = 0;
for (i = ret; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("刪除成功\n");
}
//打印通訊錄
void ShowContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通訊錄為空,打印無(wú)意義\n");
return;
}
int i = 0;
printf("%-20s%-5s%-5s%-30s%-30s\n", "姓名", "年齡", "性別", "電話", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s%-5d%-5s%-30s%-30s\n", pc->data[i].name, pc->data[i].age,
pc->data[i].gender, pc->data[i].tele, pc->data[i].addr);
}
}
//查找聯(lián)系人
void SelectContact(Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("請(qǐng)輸入要查找的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要查找的人\n");
return;
}
printf("%-20s%-5s%-5s%-30s%-30s\n", "姓名", "年齡", "性別", "電話", "地址");
printf("%-20s%-5d%-5s%-30s%-30s\n", pc->data[ret].name, pc->data[ret].age,
pc->data[ret].gender, pc->data[ret].tele, pc->data[ret].addr);
}
//修改聯(lián)系人信息
void ModifyContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("請(qǐng)輸入要修改的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要修改的人\n");
return;
}
printf("請(qǐng)輸入名字:");
scanf("%s", pc->data[ret].name);
printf("請(qǐng)輸入年齡:");
scanf("%d", &(pc->data[ret].age));
printf("請(qǐng)輸入性別:");
scanf("%s", pc->data[ret].gender);
printf("請(qǐng)輸入電話:");
scanf("%s", pc->data[ret].tele);
printf("請(qǐng)輸入地址:");
scanf("%s", pc->data[ret].addr);
}
int cmp(const void* a, const void* b)
{
return strcmp((char*)a, (char*)b);
}
//以名字排序所有聯(lián)系人
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);
printf("排序成功\n");
}
//銷毀通訊錄
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
}
3.4 結(jié)果演示
因?yàn)樵?個(gè)功能中,只修改了增加聯(lián)系人信息這一個(gè)功能,其余5個(gè)功能并未修改,因此結(jié)果演示中只演示通訊錄容量不夠時(shí)增容的情況文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-736395.html
好了,那么本篇博客就到此結(jié)束了,如果你覺(jué)得本篇博客對(duì)你有些幫助,可以給個(gè)大大的贊??嗎,感謝看到這里,我們下篇博客見(jiàn)??文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-736395.html
到了這里,關(guān)于【C語(yǔ)言】?jī)?yōu)化通訊錄管理系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!