首先感謝上一篇博客的大佬們的點贊,非常感謝?。。?/p>
目錄
前言
?一、需要添加的功能
1. 初始化——動態(tài)內(nèi)存開辟
2.添加聯(lián)系人——通訊錄擴(kuò)容
3.退出通訊錄——通訊錄銷毀
二、具體操作
1.鋪墊
2.修改初始化函數(shù)
3.修改添加函數(shù)?
4.退出通訊錄,新增銷毀函數(shù)
前言
上一篇文章我們用c語言探討了如何實現(xiàn)靜態(tài)版的通訊錄的基本邏輯。在使用通訊錄的過程中,我們可以添加、刪除聯(lián)系人的信息。如果在靜態(tài)版的通訊錄當(dāng)中執(zhí)行,我們可能會遇到通訊錄容量不夠或者容量太大造成空間浪費的問題。那么,有沒有一種方法可以讓容量不夠時自己開辟呢?這篇文章就為你解決這個問題。在原版靜態(tài)通訊錄的基礎(chǔ)上,實現(xiàn)動態(tài)版的通訊錄。(如果沒看過靜態(tài)版,指揮部幫你空降↓)
c語言實踐——通訊錄(1)(靜態(tài)版)
?一、需要添加的功能
在開始前我們首先要想好動態(tài)通訊錄需要什么樣的功能?;镜某跏蓟?、增、刪、查、改、排、退出都已實現(xiàn),但是我們希望通訊錄在一開始有一個較小的空間,在每次添加聯(lián)系人空間不夠時可以自動擴(kuò)容,這樣我們就需要對一些函數(shù)做如下修改:
1. 初始化——動態(tài)內(nèi)存開辟
初始化不應(yīng)該初始化固定的數(shù)組,而應(yīng)該將一個開辟的動態(tài)內(nèi)存賦給一個指針。這樣才能實現(xiàn)空間的動態(tài)開辟。
2.添加聯(lián)系人——通訊錄擴(kuò)容
添加聯(lián)系人的過程中,需要先檢查內(nèi)存是否夠用。如果夠用,那么程序照常進(jìn)行。如果不夠用,那么就需要在原空間后再開辟新的空間。
3.退出通訊錄——通訊錄銷毀
退出時,應(yīng)該將前面開辟的內(nèi)存銷毀,需要添加一個函數(shù)以實現(xiàn)這個功能。
二、具體操作
1.鋪墊
什么鋪墊?其實就是把前面定義的變量和常量稍作修改:
- 前面的最大數(shù)量MAX不再需要,可以刪除。
- 初始化時的通訊錄的初始容量最好在前面定義一下,方便修改。
- 每次擴(kuò)容需要增加的空間數(shù)量也要定義,后面會多次使用。
- 結(jié)構(gòu)體中數(shù)組要換成指針,后面內(nèi)存開辟會使用。
- 結(jié)構(gòu)體中的成員要添加一個表示容量的變量,來判斷通訊錄是否已滿。
修改后的代碼如下:
#define MAX_NAME 15
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 5
#define ADD_SIZE 2//擴(kuò)容時添加空間大小
#define INIT_SIZE 4//通訊錄初始空間大小
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
//靜態(tài)版
// typedef struct Contact
//{
// PeoInfo Data[MAX];
// int size;
//}Contact;
//動態(tài)版
typedef struct Contact
{
PeoInfo* Data;//將數(shù)組改為指針
int size;
int capacity;//加上容量
}Contact;
2.修改初始化函數(shù)
因為把數(shù)組改為指針,后面需要開辟空間,所以要使用malloc對指針進(jìn)行初始化。(注意包含頭文件stdlib.h)但是,開辟失敗了,就尷尬了,哈哈,所以別忘了判斷是否開辟成功。成功了才能搞下面的操作,也就是把大小改成0啦、把容量改為初始值啦。
代碼如下:
//靜態(tài)版本
//void InitContact(Contact* pc)
//{
// memset(pc, 0, sizeof(pc->Data));
// pc->size = 0;
//}
//動態(tài)版本
void InitContact(Contact* pc)
{
pc->Data = (PeoInfo*)malloc(INIT_SIZE * sizeof(PeoInfo));
if (pc->Data == NULL)
{
printf("初始化通訊錄失敗:%s\n", strerror(errno));
return;
}
pc->size = 0;
pc->capacity =INIT_SIZE;
}
3.修改添加函數(shù)?
在進(jìn)入函數(shù)后,首先要檢查通訊錄容量是否夠用。在靜態(tài)版通訊錄中,容量不夠時我們只能,害,無奈提醒,然后返回。
但是我們的動態(tài)通訊錄就強了,在不夠用時,他能擴(kuò)容!可以專門寫一個CheckContact函數(shù)來實現(xiàn)。在參數(shù)傳入,接收之后,就可以使用我們無所不能的realloc函數(shù)給指針指向的空間擴(kuò)容啦!
這里注意要判斷一下內(nèi)存是否開辟成功,如果開辟失敗就要直接返回了(沮喪.jpg)。如果開辟成功,就要讓我們的容量增加相應(yīng)的值啦。
其余的代碼就和原來的代碼一模一樣。
代碼如下:
//靜態(tài)版本
//void ContactAdd(Contact* pc)
//{
// if (pc->size == MAX)
// {
// printf("通訊錄已滿,無法添加聯(lián)系人\n");
// return;
// }
// printf("請輸入名字>:");
// scanf("%s", pc->Data[pc->size].name);
// printf("請輸入年齡>:");
// scanf("%d", &pc->Data[pc->size].age);
// printf("請輸入性別>:");
// scanf("%s", pc->Data[pc->size].sex);
// printf("請輸入電話>:");
// scanf("%s", pc->Data[pc->size].tele);
// printf("請輸入地址>:");
// scanf("%s", pc->Data[pc->size].addr);
// pc->size++;
// printf("添加成功\n");
//}
//動態(tài)版本
static void CheckCapacity(Contact* pc)
{
if (pc->size == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->Data, (pc->capacity + 2) * sizeof(PeoInfo));
if (ptr == NULL)
{
printf("CheckCapacity:%s\n", strerror(errno));//errno頭文件errno.h
return;
}
pc->Data = ptr;
pc->capacity += ADD_SIZE;
printf("增容成功,當(dāng)前容量:%d\n", pc->capacity);
}
}
void ContactAdd(Contact* pc)
{
CheckCapacity(pc);
printf("請輸入名字>:");
scanf("%s", pc->Data[pc->size].name);
printf("請輸入年齡>:");
scanf("%d", &pc->Data[pc->size].age);
printf("請輸入性別>:");
scanf("%s", pc->Data[pc->size].sex);
printf("請輸入電話>:");
scanf("%s", pc->Data[pc->size].tele);
printf("請輸入地址>:");
scanf("%s", pc->Data[pc->size].addr);
pc->size++;
printf("添加成功\n");
}
4.退出通訊錄,新增銷毀函數(shù)
最難的一步來了(煙霧彈)?。?!大家注意看,這個函數(shù)的實現(xiàn)足足需要5!行代碼!是不是難的離譜?這個函數(shù),要釋放內(nèi)存,要修改自變量為0,把指針置為空,僅此而已。
上代碼!
void DestroyContact(Contact* pc)
{
free(pc->Data);
pc->Data = NULL;
pc->size = 0;
pc->capacity = 0;
printf("釋放內(nèi)存\n");
}
聰明的你不要忘了,把這個函數(shù)的聲明寫到你創(chuàng)建的.h文件里面吶?。ㄊ裁矗阏f你已經(jīng)忘了?你這個年紀(jì)怎么能忘的?哦,你沒忘,我忘了啊,那沒事了)
那就把咱之前文件里面的代碼再寫一下,來看看完整的、能跑起來的、動態(tài)的、(還要加什么嘛,好像沒有了)**的通訊錄源碼吧!
contact.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#define MAX_NAME 15
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 5
#define ADD_SIZE 2
#define INIT_SIZE 4
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
typedef struct Contact
{
PeoInfo* Data;
int size;
int capacity;
}Contact;
void InitContact(Contact* pc);
void ContactAdd(Contact* pc);
void ShowContact(const Contact* pc);
void ContactDel(Contact* pc);
void ContactSearch(const Contact* pc);
void ContactModify(Contact* pc);
void ContactSort(Contact* pc);
void DestroyContact(Contact* pc);
test.c
#include "contact.h"
void menu()
{
printf("***************************\n");
printf("***** 1.add *****\n");
printf("***** 2.del *****\n");
printf("***** 3.search *****\n");
printf("***** 4.modify *****\n");
printf("***** 5.show *****\n");
printf("***** 6.sort *****\n");
printf("***** 0.exit *****\n");
printf("***************************\n");
}
//受用枚舉類型,提高可讀性,比define更方便,
//define把字母替換成相應(yīng)的數(shù)字,
//但是enum直接字母和數(shù)字完全相同
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
int main()
{
int input = 0;
Contact con;//定義通訊錄
//初始化通訊錄
InitContact(&con);
do
{
menu();
printf("請選擇>:");
scanf("%d", &input);
switch (input)
{
case ADD:
ContactAdd(&con);
break;
case DEL:
ContactDel(&con);
break;
case SEARCH:
ContactSearch(&con);
break;
case MODIFY:
ContactModify(&con);
break;
case SHOW:
ShowContact(&con);
break;
case SORT:
ContactSort(&con);
break;
case EXIT:
DestroyContact(&con);
printf("退出通訊錄\n");
break;
default:
printf("選擇非法,請重新選擇\n");
break;
}
} while (input);
return 0;
}
contact.c文章來源:http://www.zghlxwxcb.cn/news/detail-400638.html
#include "contact.h"
void InitContact(Contact* pc)
{
pc->Data = (PeoInfo*)malloc(INIT_SIZE * sizeof(PeoInfo));
if (pc->Data == NULL)
{
printf("初始化通訊錄失?。?s\n", strerror(errno));
return;
}
pc->size = 0;
pc->capacity =INIT_SIZE;
}
void DestroyContact(Contact* pc)
{
free(pc->Data);
pc->Data = NULL;
pc->size = 0;
pc->capacity = 0;
printf("釋放內(nèi)存\n");
}
static void CheckCapacity(Contact* pc)
{
if (pc->size == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->Data, (pc->capacity + 2) * sizeof(PeoInfo));
if (ptr == NULL)
{
printf("CheckCapacity:%s\n", strerror(errno));
return;
}
pc->Data = ptr;
pc->capacity += ADD_SIZE;
printf("增容成功,當(dāng)前容量:%d\n", pc->capacity);
}
}
void ContactAdd(Contact* pc)
{
CheckCapacity(pc);
printf("請輸入名字>:");
scanf("%s", pc->Data[pc->size].name);
printf("請輸入年齡>:");
scanf("%d", &pc->Data[pc->size].age);
printf("請輸入性別>:");
scanf("%s", pc->Data[pc->size].sex);
printf("請輸入電話>:");
scanf("%s", pc->Data[pc->size].tele);
printf("請輸入地址>:");
scanf("%s", pc->Data[pc->size].addr);
pc->size++;
printf("添加成功\n");
}
//按名字查找,找到了返回下標(biāo),找不到返回-1
//這個函數(shù)是用來輔助search和show的,所以不應(yīng)該被其他文件使用
static int FindByName(const Contact* pc, char name[MAX_NAME])
{
int i = 0;
for (i = 0; i < pc->size; i++)
{ //如果能找到
if (0 == strcmp(pc->Data[i].name, name))
{
return i;
}
}
//找不到
return -1;
}
//展示聯(lián)系人
//不應(yīng)該改變原數(shù)據(jù)
void ShowContact(const Contact* pc)
{
int i = 0;
printf("%-15s %-5s %-5s %-11s %-5s", "姓名", "年齡", "性別", "電話", "地址\n");
for (i = 0; i < pc->size; i++)
{
printf("%-15s %-5d %-5s %-11s %-5s\n", pc->Data[i].name,
pc->Data[i].age,
pc->Data[i].sex,
pc->Data[i].tele,
pc->Data[i].addr);
}
}
//刪除指定聯(lián)系人
void ContactDel(Contact* pc)
{
//1.找到要刪除的數(shù)據(jù)下標(biāo)
char name[MAX_NAME];
printf("請輸入要刪除的名字:>");
scanf("%s", name);
//如果找不到,提示后直接返回
int pos = FindByName(pc,name);//按名字查找,找到了返回下標(biāo),找不到返回-1
if (pos == -1)
{
printf("找不到指定聯(lián)系人\n");
return;
}
//2.找到了就刪除
memmove(pc->Data + pos, pc->Data + pos + 1, (pc->size - 1 - pos)*sizeof(pc->Data[0]));
pc->size--;
printf("刪除成功\n");
}
//查找聯(lián)系人
//不應(yīng)該改變原數(shù)據(jù)
void ContactSearch(const Contact * pc)
{
char name[MAX_NAME];
printf("請輸入要查找的人的名字>:");
scanf("%s", name);
int pos = FindByName(pc, name);//按名字查找,找到了返回下標(biāo),找不到返回-1
if (pos == -1)
{
printf("找不到要查找的人\n");
return;
}
printf("%-15s %-3s %-5s %-11s %-5s", "姓名", "年齡", "性別", "電話", "地址\n");
printf("%-15s %-3d %-5s %-11s %-5s\n", pc->Data[pos].name,
pc->Data[pos].age,
pc->Data[pos].sex,
pc->Data[pos].tele,
pc->Data[pos].addr);
}
//修改聯(lián)系人
void ContactModify(Contact* pc)
{
//1.查找
char name[MAX_NAME];
printf("請輸入要修改的人的名字>:");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("找不到要修改的聯(lián)系人\n");
return;
}
//修改
printf("請輸入名字>:");
scanf("%s", pc->Data[pos].name);
printf("請輸入年齡>:");
scanf("%d", &pc->Data[pos].age);
printf("請輸入性別>:");
scanf("%s", pc->Data[pos].sex);
printf("請輸入電話>:");
scanf("%s", pc->Data[pos].tele);
printf("請輸入地址>:");
scanf("%s", pc->Data[pos].addr);
printf("修改成功\n");
}
//排序
int cmp_by_name(void* e1, void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void ContactSort(Contact* pc)
{
qsort(pc->Data, pc->size, sizeof(PeoInfo), cmp_by_name);
printf("排序成功\n");
}
簡簡單單吶兄弟們(大部分都是兄弟吧?算了,加個姐妹嘻嘻)。感謝大佬們的三連(啊不,點贊,還不行,對你們要求太高了。不能這么說,應(yīng)該說我不配)感謝大佬們點開我這篇文章啊,感謝你們激勵我繼續(xù)前進(jìn)?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-400638.html
到了這里,關(guān)于C語言實踐——通訊錄(2)(動態(tài)版)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!