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

🚩write in front🚩   

🔎大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
🏅2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星Top100~阿里云专家博主 & 星级博主~掘金⇿InfoQ~51CTOP创作者~周榜109﹣总榜883⇿全网访问量35w+🏅
🆔本文由 謓泽 原创 CSDN首发🙉如需转载还请通知⚠
📝个人主页-謓泽的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​
📣系列专栏-YY_謓泽的博客-CSDN博客🎓
✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本📩

​​

目录

🚩write in front🚩   

前言

动态内存版本 

代码改动 

模块化代码实现

address_book.c

address_book.h

test.c

最后

前言

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

✨链接→【C语言】通讯录《静态内存版本》_謓泽的博客-CSDN博客

动态内存版本 

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

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

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

✨链接→【C语言】动态内存开辟的使用『malloc』

代码改动 

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

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

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

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

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

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

​​

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

​​

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

模块化代码实现

​​

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!!
}

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);

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;
}

最后

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

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

謓泽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值