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

动态内存函数的介绍

  • 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<stdlib.h>
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<stdlib.h>
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<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#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");
	}
}

 


深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xiaocaiji_k

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

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

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

打赏作者

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

抵扣说明:

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

余额充值