C语言实现通讯录(可动态扩容版)及其动态内存函数介绍

首先介绍一下本次动态扩容版本通讯录所要用到的几个动态内存函数。分别是malloc,calloc,realloc和free函数。

malloc函数

 

malloc函数是一个动态内存开辟的函数,它向内存申请一块连续可用的空间,并返回指向这块空间的指针

注意事项:

1.如果开辟成功,则返回一个指向开辟好空间的指针。

2.如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要检查是否为NULL!!!

3.返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,所以在具体使用的时候使用者需将返回值强制转换为自己所需要的类型值。

4.如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。

calloc函数

 

 注意事项:

1.该函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0.

2.与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为0。

注释:具体要用malloc或者calloc函数取决于使用者需不需将所申请的空间初始化,如果需要从初始化则用calloc,不初始化则用malloc。

 realloc函数

 

 其中ptr是要调整的内存地址,size为调整之后新大小。

注意事项:

1.realloc函数返回值为调整之后的内存起始位置

2.这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

注释:realloc在调整内存空间有两种情况。具体如下图所示:

通讯录(可动态扩容版)代码详解

 相对于静态版本的通讯录,动态版本的具体改进有以下几个部分。

1.通讯录结构体:

将原先的struct PeoInfo结构体数组data[]改为所指向动态开辟空间的结构体指针struct PeoInfo *data。新增容量capacity,每当新增的通讯录联系人个数sz达到容量capacity,开始扩容。

struct contact    //创建通讯录结构体
{
	struct PeoInfo *data;   //指向了动态开辟的空间
	int sz;    //已经放进去信息的个数
	int capacity;  //容量
};

2.通讯录初始化

静态的初始化使用memset函数将100个struct PeoInfo类型的字节大小赋为0实现通讯录的初始化,动态改进后用malloc动态开辟个DEFAULT_SZ字节的空间,DEFAULT_SZ为宏定义3,即初始容量为3个。注意!!!使用动态内存函数开辟空间,首先需判断所返回的指针是否为NULL。返回NULL则报错,不是则使用,最后一定要记得将所开辟空间free释放掉。

通讯录初始化代码如下:

void InitContact(struct contact*pc)  //用malloc动态开辟个DEFAULT_SZ字节的空间;
{ 
	assert(pc);
	pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact()");   //如果malloc开辟空间失败,返回空指针,报错
		return;
	}

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
}

3.增加通讯录中联系人信息

在原静态版Add_contact()函数的基础上增加检查容量函数check_capacity(),在增加联系人信息之前先判断容量是否已满,是否需要增容。需要增容则调用realloc函数动态新增DEFAULT_ADD*sizeof(struct PeoInfo)字节大小的空间。DEFAULT_ADD为宏定义2,即每次增容2个联系人大小。判断realloc返回值是否为NULL,是则报错,return0,否则增容成功,将realloc动态开辟的空间的首地址赋给pc->data并且容量自加,返回1。

根据check_capacity()函数的返回值判断是否增容成功返回0增容失败,返回1增容成功或者不需要增容。

增加通讯录中联系人信息代码如下:

int check_capacity(struct contact*pc)
{
	if (pc->sz == pc->capacity)  //容量已满,增容
	{
		struct PeoInfo*ptr = (struct PeoInfo*)realloc(pc->data, (DEFAULT_SZ + DEFAULT_ADD)*sizeof(struct PeoInfo));
		if (ptr != NULL) //动态开辟成功!
		{
			pc->data = ptr;   //将realloc动态开辟的空间的首地址赋给pc->data
			pc->capacity += DEFAULT_ADD;  //开辟成功,容量自加
			printf("增容成功!!!\n");
			return 1;
		}
		else
		{
			perror("Add_contact()");   //增容失败,报错
			return 0;
		}

	}
	else
	return 1;  //pc->sz未达到容量,不需要增容
}
void Add_contact(struct contact*pc) //增加通讯录中联系人信息
{
	assert(pc);
	if (0==check_capacity(pc))  //根据check_capacity()函数的返回值判断是否增容成功
		                         //返回0增容失败,返回1增容成功或者不需要增容
	{
		return;
	}

	//增加联系人信息
	printf("请输入联系人姓名:");
	scanf("%s",pc->data[pc->sz].name);
	printf("请输入联系人性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入联系人年龄:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入联系人电话:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入联系人地址:");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("成功增加联系人!\n");
}

4.销毁通讯录

因为我们使用malloc和realloc动态内存函数,使用完后需将所开辟的空间释放掉,所以就不能像之前静态版本一样直接初始化。所以当我们输入input=0时,调用Destroy_contact()函数去释放所申请的空间。具体代码如下:

void Destroy_contact(struct contact*pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

代码运行结果图

增容:

 结语

通过对于静态版本的改进,对于malloc,calloc,realloc函数的认知更加深刻,实现了通讯录的动态扩容。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通讯录管理系统是一种常见的应用程序,可以用来管理联系人的信息,包括姓名、电话号码、地址等。在C语言中,可以使用结构体来表示联系人的信息,使用文件来保存和读取联系人的信息。下面是一个简单的通讯录管理系统的实现: 1. 定义联系人结构体 ```c typedef struct { char name[20]; char phone[20]; char address[50]; } Contact; ``` 2. 定义函数来添加、删除、修改和查询联系人信息 ```c void add_contact(Contact* contacts, int* count) { printf("请输入联系人姓名:"); scanf("%s", contacts[*count].name); printf("请输入联系人电话:"); scanf("%s", contacts[*count].phone); printf("请输入联系人地址:"); scanf("%s", contacts[*count].address); (*count)++; } void delete_contact(Contact* contacts, int* count) { char name[20]; printf("请输入要删除的联系人姓名:"); scanf("%s", name); for (int i = 0; i < *count; i++) { if (strcmp(contacts[i].name, name) == 0) { for (int j = i; j < *count - 1; j++) { contacts[j] = contacts[j + 1]; } (*count)--; printf("删除成功!\n"); return; } } printf("未找到该联系人!\n"); } void modify_contact(Contact* contacts, int count) { char name[20]; printf("请输入要修改的联系人姓名:"); scanf("%s", name); for (int i = 0; i < count; i++) { if (strcmp(contacts[i].name, name) == 0) { printf("请输入新的联系人电话:"); scanf("%s", contacts[i].phone); printf("请输入新的联系人地址:"); scanf("%s", contacts[i].address); printf("修改成功!\n"); return; } } printf("未找到该联系人!\n"); } void search_contact(Contact* contacts, int count) { char name[20]; printf("请输入要查询的联系人姓名:"); scanf("%s", name); for (int i = 0; i < count; i++) { if (strcmp(contacts[i].name, name) == 0) { printf("姓名:%s\n", contacts[i].name); printf("电话:%s\n", contacts[i].phone); printf("地址:%s\n", contacts[i].address); return; } } printf("未找到该联系人!\n"); } ``` 3. 定义函数来保存和读取联系人信息 ```c void save_contacts(Contact* contacts, int count) { FILE* fp = fopen("contacts.dat", "wb"); if (fp == NULL) { printf("保存失败!\n"); return; } fwrite(contacts, sizeof(Contact), count, fp); fclose(fp); printf("保存成功!\n"); } void load_contacts(Contact* contacts, int* count) { FILE* fp = fopen("contacts.dat", "rb"); if (fp == NULL) { printf("读取失败!\n"); return; } *count = 0; while (fread(&contacts[*count], sizeof(Contact), 1, fp) == 1) { (*count)++; } fclose(fp); printf("读取成功!\n"); } ``` 4. 定义主函数实现菜单和用户交互 ```c int main() { Contact contacts[100]; int count = 0; load_contacts(contacts, &count); while (1) { printf("请选择操作:\n"); printf("1. 添加联系人\n"); printf("2. 删除联系人\n"); printf("3. 修改联系人\n"); printf("4. 查询联系人\n"); printf("5. 退出程序\n"); int choice; scanf("%d", &choice); switch (choice) { case 1: add_contact(contacts, &count); break; case 2: delete_contact(contacts, &count); break; case 3: modify_contact(contacts, count); break; case 4: search_contact(contacts, count); break; case 5: save_contacts(contacts, count); return 0; default: printf("无效的选择!\n"); break; } } } ``` 这个程序可以实现基本的通讯录管理功能,可以根据需要进行扩展和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值