动态内存管理【动态版通讯录】

动态内存函数的介绍

  • malloc
  • calloc
  • free
  • realloc

前言

为什么存在动态内存分配?

我们当前已有的内存分配可能不能满足我们的需求,它有自己的局限性,比如:

int main()

{

   int arr[10];

//我们向内存申请了40个字节的空间,这片空间开辟好了之后,大小就固定死了,

//不能变大变小,这是它的局限性,假设我要存放41个字节的数据,那空间就不够了,

//再假设我只是要存放1个字节的数据,那么多余的空间就浪费了,这样就不够灵活。

   return 0;

}

这时候就需要用到我们的动态内存函数:


提示:以下是本篇文章正文内容,下面案例可供参考

一.malloc和free

void * malloc (size_t size);

这个函数向内存申请一块连续可用的空间,并返回指向该空间的指针。

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

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

3.返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定

void free ( void * ptr );

free函数是用来释放动态开辟的内存

1.如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。

2.如果参数ptr是NULL指针,则函数什么都不做。

#include
int main()
{
	//int arr[10];
	//动态开辟
	int* p = (int*)malloc(40);
	int* ptr = p;//把初始位置保存下来
	if (ptr == NULL) //判断开辟成功还是失败
	{
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*ptr = i;
		ptr++;
	}
	//释放
	free(p);
	p = NULL;//置为空指针
	return 0;
}

二、calloc

void* calloc (size_t num, size_t size);

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

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

 

int main()
{
	//int arr[10];
	//动态开辟
	int* p = (int*)calloc(10,sizeof(int));
	int* ptr = p;//把初始位置保存下来
	if (ptr == NULL) //判断开辟成功还是失败
	{
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*ptr = i;
		ptr++;
	}
	//释放
	free(p);
	p = NULL;//置为空指针
	return 0;
}

三、realloc

void* realloc (void* ptr, size_t size);

realloc函数的出现让动态内存管理更加灵活。

有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时 候内存,我们一定会对内存的大小做灵活的调整。

那 realloc 函数就可以做到对动态开辟内存大小 的调整。

#include
int main()
{
	//int arr[10];
	//动态开辟
	int* p = (int*)calloc(10,sizeof(int));
	if (p == NULL) //判断开辟成功还是失败
	{
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p+i) = i;
	}
	//增容
	int* ptr = (int*)realloc(p, 80);
	//注意这里一定要判断释放增容成功
	if (ptr != NULL)
	{
		p = ptr;
	}
	//使用
	// ......
	//释放
	free(p);
	p = NULL;//置为空指针
	return 0;
}

 接下来用刚刚学到的函数改造一下静态通讯录:

 


                              //头文件
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#define NAME 10
#define SEX 6
#define TELE 12
#define ADDR 10
#define NUM1 3
#define NUM2 2
//表示人的信息
struct peoinfo
{
	char name[NAME];
	char sex[SEX];
	int age;
	char tele[TELE];
	char addr[ADDR];
};
//通讯录
struct contact
{
	struct peoinfo *data;//一千个人的信息
	int sz;//下标记录
	int sum;//容量计数
};
//初始化通讯录
void initcontact(struct contact* p);
//添加联系人
void addcontact(struct contact* p);
//显示通讯录
void showcontact(struct contact* p);
//删除联系人
void delcontact(struct contact* p);
//搜索联系人
void searchcontact(struct contact* p);
//清空通讯录
void emptycontact(struct contact* p);
//按照年龄排序通讯录
void sortcontact(struct contact* p);
//销毁通讯录
void quitcontact(struct contact* p);
//修改通讯录指定联系人
void modifcontact(struct contact* p);

                                  //主函数

void menu()
{
	printf("*****1.Add       2.del********\n");
	printf("*****3.search    4.modif******\n");
	printf("*****5.show      6.empty******\n");
	printf("*****7.sort      0.exit*******\n");
	printf("******************************\n");
}
int main()
{
	int input = 0;
	//创建通讯录
	struct contact con;
	//初始化通讯录
	initcontact(&con);
	do
	{
		menu();
		printf("请选择>:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 0:
			quitcontact(&con);
			break;
		case 1:
			addcontact(&con);
			break;
		case 2:
			delcontact(&con);
			break;
		case 3:
			searchcontact(&con);
			break;
		case 4:
			modifcontact(&con);
			break;
		case 5:
			showcontact(&con);
			break;
		case 6:
			emptycontact(&con);
			break;
		case 7:
			sortcontact(&con);
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

                                 //函数的实现

//初始化通讯录
void initcontact(struct contact* p)
{
	assert(p);
	//初始化开辟三个人信息的容量
	p->data=(struct peoinfo*)malloc(NUM1 * sizeof(struct peoinfo));
	if (p->data == NULL)  //判断是否开辟成功
	{
		return;
	}
	p->sz = 0;
	p->sum = NUM1;//初始化为3个人的信息的容量
}
//添加联系人
void addcontact(struct contact* p)
{
	assert(p);
	if (p->sz == p->sum)
	{
		printf("通讯录已满\n");
		//空间满了,使用realloc函数扩容
		struct peoinfo*ptr =(struct peoinfo*)realloc(p->data, (p->sum+NUM2) * sizeof(struct peoinfo));
		if (ptr == NULL)
		{
			return;
		}
		p->data = ptr;
		p->sum += NUM2;//对应的容量也要增加
		printf("扩容成功\n");
	}
	printf("请输入名字:>");
	scanf("%s", p->data[p->sz].name);
	printf("请输入性别:>");
	scanf("%s", p->data[p->sz].sex);
	printf("请输入年龄:>");
	scanf("%d", &p->data[p->sz].age);
	printf("请输入电话:>");
	scanf("%s", p->data[p->sz].tele);
	printf("请输入住址:>");
	scanf("%s", p->data[p->sz].addr);
	printf("添加联系人成功\n");
	p->sz++;
}
//显示通讯录
void showcontact(struct contact* p)
{
	assert(p);
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		printf("%-20s\t", p->data[i].name);
		printf("%-5s\t", p->data[i].sex);
		printf("%-5d\t", p->data[i].age);
		printf("%-12s\t", p->data[i].tele);
		printf("%-30s\t", p->data[i].addr);
		printf("\n");
	}
}
int findname(struct contact* p, char name[])
{
	assert(p);
	int i = 0;
	for (i = 0; i < p->sz; i++)
	{
		if (strcmp(name, p->data[i].name) == 0)
		{
			return i;
		}
	}
	return -1;
}
//删除联系人
void delcontact(struct contact* p)
{
	assert(p);
	printf("请输入要删除人的姓名\n");
	char name[20];
	scanf("%s", name);
	int ret = findname(p, name);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
	}
	else
	{
		int i = 0;
		for (i = ret; i < p->sz - 1; i++)
		{
			p->data[i] = p->data[i + 1];
		}
		printf("成功删除联系人\n");
		p->sz--;
	}
}
//搜索联系人
void searchcontact(struct contact* p)
{
	assert(p);
	printf("请输入要搜索人的姓名:>\n");
	char name[20];
	scanf("%s", name);
	int ret = findname(p, name);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
	}
	else
	{
		printf("%-20s\t", p->data[ret].name);
		printf("%-5s\t", p->data[ret].sex);
		printf("%-5d\t", p->data[ret].age);
		printf("%-12s\t", p->data[ret].tele);
		printf("%-30s\t", p->data[ret].addr);
		printf("\n");
	}
}
//清空通讯录
void emptycontact(struct contact* p)
{
	assert(p);
	memset(p->data, 0, p->sz * sizeof(struct peoinfo));
	p->sz = 0;
	//释放内存,指针置为NULL
	free(p->data);
	p->data = NULL;
	printf("已清空通讯录\n");

}
//排序通讯录
int cmp(const void* e1, const void* e2)
{
	return ((struct peoinfo*)e1)->age - ((struct peoinfo*)e2)->age;
}
void sortcontact(struct contact* p)
{
	assert(p);
	qsort(p->data, p->sz, sizeof(struct peoinfo), cmp);
}
//退出通讯录,并释放内存。
void quitcontact(struct contact* p)
{
	assert(p);
	free(p->data);
	p->data = NULL;
	printf("退出游戏\n");
}
//修改通讯录指定联系人
void modifcontact(struct contact* p)
{
	assert(p);
	printf("请输入联系人名字;>\n");
	char name[20];
	scanf("%s", &name);
	int ret = findname(p, name);
	if (ret == -1)
	{
		printf("没有该联系人\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", p->data[ret].name);
		printf("请输入性别:>");
		scanf("%s", p->data[ret].sex);
		printf("请输入年龄:>");
		scanf("%d", &p->data[ret].age);
		printf("请输入电话:>");
		scanf("%s", p->data[ret].tele);
		printf("请输入住址:>");
		scanf("%s", p->data[ret].addr);
		printf("修改成功\n");
	}
}

 


你可能感兴趣的:(c)