您的位置:首页 > 文旅 > 美景 > 宁波网络优化seo_设计师网站behance_网站推广教程_营销网络是什么

宁波网络优化seo_设计师网站behance_网站推广教程_营销网络是什么

2025/4/30 14:45:22 来源:https://blog.csdn.net/HDSTQTW/article/details/146609703  浏览:    关键词:宁波网络优化seo_设计师网站behance_网站推广教程_营销网络是什么
宁波网络优化seo_设计师网站behance_网站推广教程_营销网络是什么

目录

一.引入枚举

二.动态内存开辟

contact.h

1.初始化

最终代码

2.扩容

最终代码

3.退出自动销毁空间

4.减容

最终代码

三.依姓名排序


通讯录1.0里的 PeoInfo data[MAX] 一次开辟定了内存空间。我放150个人空间不够。只放15个人又太浪费空间。

我们对通讯录1.0进行改造升级。
扩容:方便测试,先给3个内存空间,以后当前联系人数量 == 最大联系人数量时,最大容量增加2个内存空间。
减容:当最大人数比现有人数多5个以上,减容最大人数3个内存空间。



一.引入枚举

test.c 的 switch 语句中的 case 1:   case 2:  ......我们写代码时很容易忘记这些 1,2......分别代表什么含义。
枚举常量的下标默认从0开始,每次增加1 。我们引入枚举常量。
这样在 case x:这里就能看到想要干什么。

test.c

enum Option
{EXIT,//0ADD, //1DEL, //2SEARCH,MODIFY,SHOW,SORT,DELALL
};switch (input)
{
case ADD:AddContact(&con);break;
case DEL:DelContact(&con);break;
case SEARCH:SearchContact(&con);break;
case MODIFY:ModifyContact(&con);break;
case SHOW:ShowContact(&con);break;
case SORT:break;
case DELALL:DelAllContact(&con);break;
case EXIT:printf("退出通讯录\n");break;
default:printf("输入错误\n");break;
}

二.动态内存开辟

我们要改造,PeoInfo data[MAX] 这里就不能是数组了。

contact.h

//静态版本
typedef struct Contact
{PeoInfo data[MAX];//存放人的信息int sz;//当前已经存入联系人的个数
}Contact;

我们要用 malloc 开辟一块空间,把地址存起来。
所以,要把 data 改为 PeoInfo * 类型的指针。由 data 指向开辟的空间。data 指向空间里存放人的信息。

除了 data,sz ,还需要记录当前最大容量。

#include <stdlib.h>#define DEFAULT_SZ 3 //通讯录默认大小
#define INC_SZ 2 //每次增加
#define RED_SZ 3 //每次减少
#define DIFF_SZ_CAPA 5 //最大 - 当前 的差值//动态版本
typedef struct Contact
{PeoInfo* data;//指向存放人信息的空间int sz;//当前已经存入联系人的个数int capacity;//当前通讯录的最大容量
}Contact;

 现在data 还没有指向的空间。

1.初始化

contant.c

//静态版本
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}

pc->sz = 0;肯定是不用变的。这里就不能用 memset 了,要用 malloc 开辟内存空间。


我们先开辟空间,再指定通讯录默认大小为3 。这样更合理。

//动态版本
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SZ);pc->capacity = DEFAULT_SZ;
}

malloc 的参数是要开辟内存的大小(字节)。
所以我们代码中 malloc 参数部分是:一个人的大小 * 通讯录默认人数 = 要开辟字节数

malloc 返回类型 void*  。用 pc 指向的 data 指针接收。data 的类型:PeoInfo *   。所以强制转换。


malloc 是不对开辟的内存空间初始化的。上面这样写,我们要初始化。
所以我用 calloc 。它初始化内存空间的每个字节为0

  为 num 个大小为 size 的元素开辟内存空间。

//动态版本
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));pc->capacity = DEFAULT_SZ;
}

同时,我们要对开辟的空间进行维护,判断是否开辟成功。
直接用 pc->data 接收不合适

最终代码

//动态版本
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;PeoInfo* ptr = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));if (ptr == NULL){perror("InitContact:calloc");return;}pc->data = ptr;pc->capacity = DEFAULT_SZ;
}

2.扩容

contact.c

改为动态开辟版本,里面放了元素,放不下时,要考虑扩容问题。对 Add 更改。

//静态版本
void AddContact(Contact* pc)
{assert(pc);if (pc->sz == MAX){printf("通讯录已满,无法添加\n");return;}//增加一个人的信息printf("请输入名字:");......pc->sz++;
}

动态版本不存在放满的情况,这里不用判断 == MAX


每次添加联系人后进行判断,当最大空间人数 capacity == 当前空间人数 sz 时,扩容。

//动态版本
void AddContact(Contact* pc)
{assert(pc);//增加一个人的信息......if (pc->sz == pc->capacity){//扩容}pc->sz++;
}

用 realloc 对 data 指向的空间调整。扩容的地方分装成函数。

 
ptr 是要调整的内存地址   size 是调整后的新大小(字节)。返回开辟好新空间的起始地址。

若当最大空间人数 capacity != 当前空间人数 sz 时,不扩容,直接返回。
新大小(字节) = 增加后的人数 * 每个人的大小。
判断是否成功开辟新空间,若是,再将 ptr 传给 pc->data 

最终代码

void check_capacity(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){//扩容PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){perror("check_capacity:realloc");return;}pc->data = ptr;pc->capacity += INC_SZ;//当前通讯录的最大容量再自增2}
}//动态版本
void AddContact(Contact* pc)
{assert(pc);//增加一个人的信息printf("请输入名字:");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:");scanf("%s", pc->data[pc->sz].sex);printf("请输入地址:");scanf("%s", pc->data[pc->sz].addr);printf("请输入电话:");scanf("%s", pc->data[pc->sz].tele);pc->sz++;check_capacity(pc);printf("\n当前联系人数量:%d\n", pc->sz);printf("当前最大容量:%d\n", pc->capacity);
}

3.退出自动销毁空间

当程序退出时,空间要销毁,free

//test.c
case EXIT:DestroyContact(&con);printf("退出通讯录\n");break;//contact.h  销毁内存空间
void DestroyContact(Contact* pc);//contact.c
void DestroyContact(Contact* pc)
{assert(pc);free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;pc = NULL;
}

4.减容

我们还是要判断通讯录是否为空,为空无法删除。
只需在 chack_capacity 函数中加上减容部分,再在 DelContact 函数中加几条语句即可。

最终代码

void check_capacity(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){//扩容}if ((pc->capacity - pc->sz) > DIFF_SZ_CAPA){//减容PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity - RED_SZ) * sizeof(PeoInfo));if (ptr == NULL){perror("check_capacity:realloc");return;}pc->data = ptr;pc->capacity -= RED_SZ;}
}//动态版本
void DelContact(Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}//查找printf("请输入要删除的人的名字:>");scanf("%s", name);int ret = FindByName(pc, name);if (-1 == ret){printf("要删除的人不存在\n");return;}int i = 0;//删除for (i = ret; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");check_capacity(pc);printf("\n当前联系人数量:%d\n", pc->sz);printf("当前最大容量:%d\n", pc->capacity);
}

三.依姓名排序

qsort 函数。(点击 qsort 查看详细说明)

//contact.c
int sortcon_byname(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}void SortContact_ByName(Contact* pc)
{assert(pc);qsort(pc->data, pc->sz, sizeof(PeoInfo), sortcon_byname);printf("排序成功\n");
}//test.c
case SORT:SortContact_ByName(&con);break;
//contact.h
void SortContact_ByName(Contact* pc);

错误写法:

int sortcon_byname(const void* e1, const void* e2)
{return strcmp(((Contact*)e1)->data->name, ((Contact*)e2)->data->name);
}

e1,e2 分别是要比较的两个元素的地址
比较的是人的信息PeoInfo 

我们发现,2.0版本的通讯录,程序关闭,不保存这次运行时Add的联系人。
下次运行,按5显示联系人时,是空白。
怎么解决?

期待通讯录3.0

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com