通讯录的实现(优化)【动态开辟+文件管理】

一、通讯录(优化后)实现所需知识

 经过上期的通讯录的实现,我们可以发现以下几个很明显的问题,一则:通讯录开辟的空间是静态的,我们不能更合理高效的利用开辟的空间,去存储联系人。二则:通讯录联系人的所有信息,都是写在内存上的,随着内存的关闭,所有联系人的信息,都被清空,再次打开这个程序,也找不回之前的信息。

这些问题,利用---动态内存开辟---文件管理---的知识是很容易解决的。若仍有诸多不解,可由以下链接跳转相关内容的详细归纳,以及简易通讯录的实现思路。

动态内存管理-CSDN博客

文件管理【详解归纳】-CSDN博客

通讯录项目的实现-CSDN博客

二、通讯录——动态开辟通讯录大小的讲解

1.通讯录变量的实现

通讯录的实现(优化)【动态开辟+文件管理】_第1张图片

这里依然是建立两个结构体,第一个结构体类型是联系人类型。第二个结构体则是通讯录类型。这里通讯录结构体的三个参数进行详细说明。第一个参数,代表的是目前通讯录所能存储人的最大容量。第二参数,代表是目前通讯录,已保存联系人的个数。第三个参数,则是利用了一个柔性数组知识(柔性数组【详解】-CSDN博客)。进行的动态内存开辟。

2.如何进行初始化

通讯录的实现(优化)【动态开辟+文件管理】_第2张图片

通讯录的实现(优化)【动态开辟+文件管理】_第3张图片

其实吧,通讯录的初始化,倒是挺简单的,只要掌握malloc函数怎么用,以及柔性数组如何开辟空间就能解决了。

这里我们既然运用到了柔性数组的知识,则得谨记用sizeof对结构体类型进行大小测量,是不包括柔性数组的大小的,所有这里的sizeof(contact)的值为8,我们若想达到我们想要开辟联系人大小大空间,则必须超出这个值,这里我为了方便实现通讯录的各个功能,仅仅多开辟了3个联系人大小的空间:3*sizeof(people);

不要忘了,亲自将con->count 亲自赋值当前通讯录的最大容量,其次不要忘了将con-> 亲自赋值为0,因为malloc这函数,只负责开辟空间,不负责初始化。

因为函数里面创建的变量,在离开这个函数的时候,会进行销毁,所以我们得把刚刚在堆区开辟的内存空间地址返回给函数外面的变量。

这里为了达到函数的高内聚低耦合,我选择了返回void* 类型的指针。

(这里被注释掉的语句是从外存(磁盘)中读取联系人信息到内存中)

3.如何进行扩容处理

通讯录的实现(优化)【动态开辟+文件管理】_第4张图片

这是主函数里面的部分代码:通讯录的实现(优化)【动态开辟+文件管理】_第5张图片

这里的CHANGE_INT 是我用define定义过的,其值为2。

除了要讲解如何进行扩容处理外,需强调下易错的地方,不要看我函数里面的参数也设置的con,此con与外面的那个con,不一样,函数里面的con是外面那个con的临时拷贝。realloc函数返回值有三种情况,其一:若旧内存空间后面的空间足够,则直接在后面追加空间,其二若旧空间后面的空间不够,则重新在堆区找一片空间,并将所有信息拷贝到新空间中,同时销毁之前的空间。所以函数里面con指向的是一片新的空间,在扩容函数结束销毁,但是函数里面的con和函数外面的con不一样,所以函数外面的con仍指向旧空间的地址,不仅会造成通讯录的数据难以访问,而且这样会造成程序出错。所以我们同样返回void*类型的指针。重新赋值给函数外面的con;

三、通讯录——如何保存信息到磁盘上与每次打开通讯录加载信息到内存的讲解 

通讯录的实现(优化)【动态开辟+文件管理】_第6张图片

通讯录的实现(优化)【动态开辟+文件管理】_第7张图片

这里只是涉及到了文件管理的应用。故没有什么注意事项需要强调。其从外存读取数据到内存为何需要返回void*类型的指针,则因为里面嵌套了一个扩容函数。

唯一注意事项是,要谨记文件管理的正确操作,打开文件——使用文件——关闭文件,因为涉及文件缓冲区问题。

你可能感兴趣的:(c语言,开发语言)