【C语言】通讯录《动态内存版本》

时间:2023-02-26 21:59:12

????write in front????   

????大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流????

????2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4~2021博客之星TOP100~2022博客之星TOP63~作者周榜84﹣作者总榜704~阿里云专家博主 & 阿里云星级博主~掘金优秀创作者⇿InfoQ创作者⇿51CTO红人⇿全网访问量50w+????

????本文由 謓泽 原创 如需转载还请通知⚠

????个人主页-​謓泽51Ctop的博客​????

????欢迎各位→点赞???? + 收藏⭐️ + 留言????

????系列专栏-​謓泽51Ctop的博客_【C语言】从0~1_51CTO博客​????
✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本????

前言

这篇博客带大家实现通讯录的一个动态内存增长的一个版本,在上一片博客当中我们介绍了通讯录静态版本的一个实现,如果对静态版本感兴趣的话可以看看ヾ(^▽^*)))

动态内存版本 

①:通讯录初始化后,能够存放三个人的信息。当然实际上这里多少都是可以的,只不过这个比较好测试。

②:当我们空间的存放存放满的时候,再次增加两个人的信息。

当然如果你不熟悉什么是动态内存的话,可以看看博主写的这篇博客ヾ(^▽^*)))

代码改动 

根据上篇的静态通讯录进行了一点改动,改动如下所示????

通讯录 ✨ 静态版本 →(改编成) 通讯录 ✨ 动态版本

还改变了点宏定义把原先1000人存放进来的信息删除了,增加了"容器"以及增量。

InitContact()增加人的信息,放在通讯录当中去从静态版本 ✨ →(改编成) ✨ 动态版本。

Destory_Contact()增加了一个销毁通讯录。

说明⇢在这里给大家看看程序增容后的运行界面。在这里我们的"容器值"最大为三每次增量加2的。 


【C语言】通讯录《动态内存版本》

这里是当我们输入第三次添加之后就会出现增加联系人成功(@^0^),表明我们已经动态内存开辟增容成功。


【C语言】通讯录《动态内存版本》

此时,再输入就会显示增加联系人成功,因为我们每次增量加2的。内存空间已满又要向堆区申请内存空间。

模块化代码实现


【C语言】通讯录《动态内存版本》

address_book.c

示例代码如下↓ 

#define _CRT_SECURE_NO_WARNINGS 1
#include"address_book.h"

//动态版本
void InitContact(Contact* pc)
{
pc->date = (information*)malloc(Defsz * sizeof(information));
//如果返回的为空指针的情况
if (pc->date == NULL)
{
perror("InitContact:");
return;
}
pc->sz = 0;//sz初始化
pc->capacity = Defsz;//当前最大"容量"
}

//动态版本增加
void Add_Contact(Contact* pc)
{
//当记录当前通讯录有效信息的个数 等于 表示当前通讯录的最大"容量"大小。
if (pc->sz == pc->capacity)
{
//给堆区增加"容量",因为空间不够。
information* pa = (information*)realloc(pc->date, (pc->capacity + Inc)*(sizeof(information)));
if (pa != NULL)
{
pc->date = pa;//把这块空间移交到date进行维护
pc->capacity = pc->capacity + Inc;//由于这里我们进行了增容也需要把容量改变成+Inc的值
color(12);
printf("增加联系人已成功(@^0^)\n");
}
//增容失败
else
{
perror("Add_Contact:");
printf("增加联系人失败!(ToT)/~~~\n");
return;
}
}
//增加一个人的信息
printf("\n");
printf("请输入增加人的名字->:");
scanf("%s", pc->date[pc->sz].name);//注意→数组名是首元素地址,所以不用进行取地址.

printf("请输入增加人的年龄->:");
scanf("%s", pc->date[pc->sz].age);

printf("请输入增加人的性别->:");
scanf("%s", pc->date[pc->sz].genger);

printf("请输入增加人的电话->:");
scanf("%s", pc->date[pc->sz].telephone);

printf("请输入增加人的地址->:");
scanf("%s", pc->date[pc->sz].address);
//成功~
pc->sz++;
printf("★恭喜你~添加信息成功★\n");
printf("\n");
}
void Print_Contact(const Contact* pc)
{
int i = 0;
//打印标题栏的信息
printf("|-------------------------------------------------------|\n");
printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");

for (i = 0; i < pc->sz; i++)
{
printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", pc->date[i].name,
pc->date[i].age,
pc->date[i].genger,
pc->date[i].telephone,
pc->date[i].address);
}
}

static int FindByname(Contact* pc, char name[])
{
int i = 0;
//用for循环进行遍历
for (i = 0; i < pc->sz; i++)
{
//strcmp()比较字符串
if (strcmp(pc->date[i].name, name) == 0)
{
return i;//返回下标
}
}
return -1;
}

void DeLete_Contact(Contact* pc)
{
char name[Max_name] = { 0 };
//通讯录为空的时候
if (pc->sz == 0)
{
printf("通讯录当中没有任何信息\n");
return;
}
printf("请输入你要删除的名字->:");
scanf("%s", name);
//查找要删除的人:有/没有
int ret = FindByname(pc, name);
if (ret == -1)
{
printf("没有查找到当前人的信息\n");
return;
}
//删除
int i = 0;
for (i = ret; i < pc->sz - 1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->sz--;//因为我们删除成功下标要减1
printf("★恭喜你~删除信息成功★\n");
printf("\n");
}

void Find_Contact(Contact* pc)
{
char name[Max_name] = { 0 };
printf("请输入你要查找的名字->:");
scanf("%s", name);
int ret = FindByname(pc, name);
if (ret == -1)
{
printf("没有查找到当前人的名字\n");
return;
}
else
{
printf("|-------------------------------------------------------|\n");
printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");

printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n",
pc->date[ret].name,
pc->date[ret].age,
pc->date[ret].genger,
pc->date[ret].telephone,
pc->date[ret].address);
printf("查找%sの信息成功~\n", pc->date[ret].name);
}
}

void Revise_Contact(Contact* pc)
{
char name[Max_name] = { 0 };
printf("请输入你要修改通讯录人的名字->:");
scanf("%s", name);
int ret = FindByname(pc, name);
if (ret == -1)
{
printf("当前修改人的信息不存在\n");
return;
}
else
{
printf("请输入修改人的名字->:");
scanf("%s", pc->date[ret].name);//注意→数组名是首元素地址,所以不用进行取地址.

printf("请输入修改人的年龄->:");
scanf("%s", pc->date[ret].age);

printf("请输入修改人的性别->:");
scanf("%s", pc->date[ret].genger);

printf("请输入修改人的电话->:");
scanf("%s", pc->date[ret].telephone);

printf("请输入修改人的地址->:");
scanf("%s", pc->date[ret].address);
printf("恭喜你,修改成功~\n");
}
}

int sort_name_max(const void* e1, const void* e2)
{
return (strcmp(((struct Contact*)e1)->date->name, ((struct Contact*)e2)->date->name));
}

void Check_Contact(Contact* pc)
{
//qosrt()函数首字母进行排序
qsort(pc->date, pc->sz, sizeof(pc->date[0]), sort_name_max);
printf("|-------------------------------------------------------|\n");
printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", pc->date[i].name,
pc->date[i].age,
pc->date[i].genger,
pc->date[i].telephone,
pc->date[i].address);
}
}

void Destory_Contact(Contact* pc)
{
//销毁通讯录实际上就是把date给释放掉,free()函数进行回收即可。
free(pc -> date);
pc->date = NULL;
pc->sz = 0;
pc->capacity = 0;
//记得清0☆⌒(*^-゜)v THX!!
}

【C语言】通讯录《动态内存版本》

address_book.h

示例代码如下↓  

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<string.h>

#define Max_name 5
#define Max_age 100
#define Max_genger 3
#define Max_address 20
#define Max_telephone 20

#define Defsz 3 //一开始的值
#define Inc 2 //每次的增量

//类型的定义
typedef struct information
{
//名字、年龄、性别、电话、地址。
char name[Max_name];
char age[Max_age];
char genger[Max_genger];
char telephone[Max_telephone];
char address[Max_address];
}information;

//初始化通讯录
void InitContact(Contact* pc);
//增加通讯录信息
void Add_Contact(Contact* pc);
//打印通讯录的信息
void Print_Contact(const Contact* pc);
//删除通讯人的信息
void DeLete_Contact(Contact* pc);
//查找指定通讯录人的信息
void Find_Contact(Contact* pc);
//修改指定通讯录人的信息
void Revise_Contact(Contact* pc);
//排查通讯录当中人员的信息
void Check_Contact(Contact* pc);
//销毁通讯录
void Destory_Contact(Contact* pc);

【C语言】通讯录《动态内存版本》

test.c

示例代码如下↓  

#include"address_book.h"
#include<Windows.h>
//颜色函数
void color(short x)
{
if (x >= 0 && x <= 15)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);
else
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
//创建菜单函数
void menu()
{
color(0);//黑色
system("cls");//清屏

color(12);//白色
printf("¤--------------------------------------------¤\n");
printf("|■■■■■■■■→通讯录v1.0←■■■■■■■■|\n");
printf("|———————————————————————|\n");
printf("|★★★★★→1.increase ■ 2.deLete←★★★★★|\n");
printf("|★★★★★→3.find ■ 4.Revise←★★★★★|\n");
printf("|★★★★★→5.Check ■ 6.Print ←★★★★★|\n");
printf("|★★★★★→0.Exit ■ ←★★★★★|\n");
printf("|———————————————————————|\n");
printf("|■■■■■■■■→通讯录v1.0←■■■■■■■■|\n");
printf("¤--------------------------------------------¤\n");
}
enum Number
{
Exit,
Increase,
DeLete,
Find,
Revise,
Check,
Print,
};
int main(void)
{
menu();
int input = 0;
//当然初始化全0:Contact con = {0};也是可以的,当然我们这里的初始化不是这样的原因是可以应对比较复杂的问题。
Contact con;//初始化通讯录
//给date申请一块连续的内存空间存放在堆区上。
InitContact(&con);
do
{
color(5);
printf("¤----------------¤\n");
printf("|请输入界面上的数字|:");
scanf("%d", &input);
printf("¤----------------¤\n");
color(1);
switch (input)
{
case Exit:
//把通讯录里面的内存空间date给释放掉。
Destory_Contact(&con);//销毁通讯录。
printf("══════════════@\n");
printf("退出通讯录v1.0@\n");
printf("══════════════@\n");
break;
case Increase:
//增加人的信息,放在通讯录当中去。
Add_Contact(&con);
break;
case DeLete:
//删除通讯人的信息
DeLete_Contact(&con);
break;
case Find:
//查找指定通讯录人的信息
Find_Contact(&con);
break;
case Revise:
//修改指定通讯录人的信息
Revise_Contact(&con);
break;
case Check:
//排查通讯录当中人员的信息
Check_Contact(&con);
break;
case Print:
//打印通讯录当中人员的信息。
Print_Contact(&con);
break;
default:printf("你输入的数字找不到,请重新输入~\n");
}
} while (input);
return 0;
}

【C语言】通讯录《动态内存版本》

【C语言】通讯录《动态内存版本》

最后

以上就是实现动态内存的实现方法了(^∀^●)ノシ。 

【C语言】通讯录《动态内存版本》