C语言动态内存开辟经典笔试题分析及优化通讯录

目录

1.笔试题分析

1.1  题1

1.2 题2

1.3 题3

1.4 题4

2. 优化通讯录

2.1 通讯录成员

2.2 初始化函数

2.3 扩容函数

2.4 销毁函数


1.笔试题分析

1.1  题1

void GetMemory(char* p)
{
	p = (char*)malloc(100);
}

void test(void)
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
}

int main()
{
	test();
	return 0;
}

大家可以尝试寻找出其中的错误

我们首先可以看程序运行的结果。

 并没有打印出字符串。

分析:

1. 形参p 只是 实参str 的一份临时拷贝,对于形参的修改,不会影响到实参。所以str 实际上还是空指针。

2. strcpy,printf 对空指针 ptr操作,这都是有问题的。

3.使用malloc开辟动态内存空间后,未判断是否开辟成功

4.没有释放开辟的动态内存空间。

修正代码(只是按照题意修改,其实不用这么繁琐)

char* GetMemory(char** p)
{
	char* p1 = NULL;

	p1= (char*)malloc(100);
	if (p1 != NULL)
	{
		*p = p1;
	}
	else
	{
		perror("malloc");
	}
}

void test(void)
{
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
}

int main()
{
	test();
	return 0;
}

1.2 题2

char* GetMemory(void)
{
	char p[] = "hello world";
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

int main()
{
	test();
	return 0;
}

 并没有按照预期打印“hello world”

char p[] = " hello world" 它的生命周期只在它的作用域,出了GetMemory函数后,就被销毁。此时返回的指针 p 实质上是一个野指针,它指向的内容空间已经随着函数的结束,返回给操作系统,此时内容是未知。所以我们会看到屏幕打印的是随机的。

1.3 题3

void GetMemory(char**p,int num)
{
	*p = (char*)malloc(num);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str,100);
	strcpy(str, "hello");
	printf(str);
}

int main()
{
	test();
	return 0;
}

有问题吗?没有判断内存是否开辟成功,小瑕疵。

其次,malloc函数申请空间后,没有释放。

1.4 题4

void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

int main()
{
	test();
	return 0;
}

 存在一个很典型的错误,free函数释放空间后,没有将指针 str 置空,此时指针指向的内存空间已经返回给操作系统了,此时指针str 为野指针,后续的操作都是不合理的。

其次,他在开辟动态内存空间时,也没有判断是否开辟成功。

2. 优化通讯录

http://t.csdn.cn/yU5Lq

这是我的关于静态版本的通讯录的博客在这博客中,我们选择直接创造可以保存1000个联系信息的数组。这种做法第一浪费资源,第二超出1000时,我们就无法使用。我们可以用动态内存开辟的方式,实现一个动态的通讯录程序。

2.1 通讯录成员

typedef struct contact
{
	int sz;
	peoinfo*data ;
	int capacity;

}contact;

相对于静态版本,我们的通讯录结构体成员,多了一个capacity (容量),便于和sz 比较及时扩容,同时采取地址的方式(peoinfo * data)创造数组,可以实现动态化管理内存

2.2 初始化函数

#define capMAX 3

void Init_Contact(contact* pc)
{
	pc->sz = 0;
	pc->capacity = capMAX;
	pc->data = (peoinfo*)malloc(pc->capacity * sizeof(peoinfo));
    if (pc->data == NULL)
	  {
	 	perror("Init_Contact:malloc:");
	  }
}

初始容量定位3 ,使用malloc函数开辟。同时判断是成功开辟。

2.3 扩容函数

扩容函数的应用较多,我们选择封装成独立的函数

void cheak_capacity(contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		pc->data = (peoinfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(peoinfo));
		if (pc->data == NULL)
		{
			perror("check_capacity:realloc:");
			return;
		}
		pc->capacity += 2;
	}

	printf("增容成功!");
}

realloc函数扩容。在增加联系人时,需要考虑到扩容问题,所以在增加联系人信息时,先调用一次扩容函数

2.4 销毁函数

我们使用malloc函数和realloc函数后,需要主动释放。我们选择在退出通讯录时,调用销毁函数,释放申请的动态内存空间。

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

其他的功能实现和静态版本相同,不做更改。

源码分享Contact2.0 · 斯文/mytest - 码云 - 开源中国 (gitee.com)

谢谢观看。

 

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...