C语言之动态内存管理实现通讯录(完整版)

我们在之前的博客中写过静态版的通讯录,我们今天来写一个动态版的,不需要规定它到底需要多大空间,只要还有内存,我们都可以存放的下!同时,函数实现原理,我在通讯录静态版的博客里做了详细的讲解,这里就不详细分析了,不了解原理的小伙伴们可以去C语言通讯录静态版了解一下!

目录

1.函数各部分功能

1.1初始化通讯录

1.2检测通讯录是否需要增容

1.3增加联系人

1.4删除联系人

1.5显示联系人

1.6按名字查找联系人

1.7查找指定联系人

1.8修改指定联系人的信息

1.9对所有联系人按姓名进行排序

1.10销毁通讯录,进行动态空间内存的释放

2.函数源码

2.1test.c测试代码

2.2contact.c函数各功能实现代码

2.3contact.h实现通讯录所需要的头文件代码

3.运行结果


我们在以前静态 的基础上不仅加入内存动态管理,还加入枚举,增强代码的可读性,同时我在代码难以理解的地方增加了详细的注释,相信大家可以理解!

1.函数各部分功能

1.1初始化通讯录

//初始化这个通讯录,初始化为对应的值
void InitContact(Contact* pc)
{assert(pc);//为通讯录存放人的信息的结构体分配初始空间,并把里面数据直接//初始化为0,calloc函数很合适PeopInfo* str = (PeopInfo*)calloc(DEFAULT_SZ, sizeof(PeopInfo));if (str == NULL){perror("calloc");return;}pc->data = str;pc->sz = 0;pc->capacity = DEFAULT_SZ;
}

1.2检测通讯录是否需要增容

//空间增容函数
void check_capacity(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){//通讯录已满,进行增容PeopInfo* str = (PeopInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeopInfo));if (str == NULL){perror("realloc");return;}pc->data = str;pc->capacity += INC_SZ;//总容量增加printf("空间增容成功,可以继续添加联系人\n");}
}

1.3增加联系人

//增加通讯录联系人
void AddContact(Contact* pc)
{assert(pc);check_capacity(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].Tele);printf("请输入联系人家庭住址:>");scanf("%s", pc->data[pc->sz].Addr);pc->sz++;
}

1.4删除联系人

//删除指定联系人
void DelContact(Contact* pc)
{assert(pc);char Name[NAME_MAX] = { 0 };int i = 0;if (pc->sz == 0){printf("通讯录为空,无法删除!\n");return;}printf("请输入要删除的人的姓名:>");scanf("%s", Name);int pos = FindByName(pc, Name);if (pos == -1){printf("要删除的联系人不存在!\n");return;}for (i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除联系人成功!\n");
}

1.5显示联系人

//显示所有联系人
void ShowContact(const Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法显示!\n");return;}int i = 0;printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n","姓名","年龄","性别","电话号码","家庭住址");for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",pc->data[i].Name,pc->data[i].Age,pc->data[i].Sex,pc->data[i].Tele,pc->data[i].Addr);}
}

1.6按名字查找联系人

//通过名字查找
int FindByName(const Contact* pc, char* Name)
{assert(pc);int i = 0;if (pc->sz == 0){printf("通讯录为空,无法查找!");return;}for (i = 0; i < pc->sz; i++){if (strcmp(Name, pc->data[i].Name) == 0)return i;}return -1;
}

1.7查找指定联系人

//查找指定联系人
void SehContact(const Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法查找!\n");return;}char Name[NAME_MAX] = { 0 };printf("请输入要查找的人的姓名:>");scanf("%s", Name);int pos = FindByName(pc, Name);if (pos == -1){printf("要查找的联系人不存在!\n");return;}printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话号码", "家庭住址");printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",pc->data[pos].Name,pc->data[pos].Age,pc->data[pos].Sex,pc->data[pos].Tele,pc->data[pos].Addr);
}

1.8修改指定联系人的信息

//修改指点联系人的信息
void MofContact(Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法修改!\n");return;}char Name[NAME_MAX] = { 0 };printf("请输入要修改的人的姓名:>");scanf("%s", Name);int pos = FindByName(pc, Name);if (pos == -1){printf("要修改的联系人不存在!\n");return;}printf("请输入联系人姓名:>");scanf("%s", pc->data[pos].Name);printf("请输入联系人年龄:>");scanf("%d", &pc->data[pos].Age);printf("请输入联系人性别:>");scanf("%s", pc->data[pos].Sex);printf("请输入联系人电话号码:>");scanf("%s", pc->data[pos].Tele);printf("请输入联系人家庭住址:>");scanf("%s", pc->data[pos].Addr);
}

1.9对所有联系人按姓名进行排序

//对所有联系人按姓名进行排序
void SortContact(const Contact* pc)
{assert(pc);int i = 0;int j = 0;for (i = 0; i < pc->sz; i++){for (j = i; j < pc->sz; j++){if (strcmp(pc->data[i].Name, pc->data[j].Name) > 0){PeopInfo temp[] = { 0 };temp[0] = pc->data[i];pc->data[i] = pc->data[j];pc->data[j] = temp[0];}}}ShowContact(pc);//显示一下排列结果
}

1.10销毁通讯录,进行动态空间内存的释放

//销毁通讯录,释放动态内存空间
void DestoryContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;pc = NULL;printf("通讯录已销毁\n");
}

2.函数源码

2.1test.c测试代码

//创建一个动态空间内存通讯录,里面存放人的信息,包括姓名,年龄,性别
//电话号码和家庭住址
//结合枚举,必要时要增容
//它包括一下功能
//1.增加联系人
//2.删除指定联系人
//3.查找指定联系人
//4.修改指定联系人
//5.显示所有联系人
//6.对所有联系人进行排序(按姓名)
//7.退出通讯录(这时要记得释放动态内存开辟的空间,避免内存泄漏#include"contact.h"//引用自己创建的头文件,用双引号//加入枚举,给下面Switch case语句一个提示,函数写到了通讯录的哪个功能
enum contact
{exitContact,addContact,delContact,showContact,sehContact,mofContact,sortContact,
};
void menu(void)
{printf("*******************************************\n");printf("**********     1.AddContact      **********\n");printf("**********     2.DelContact      **********\n");printf("**********     3.ShowContact     **********\n");printf("**********     4.SehContact      **********\n");printf("**********     5.MofContact      **********\n");printf("**********     6.SortContact     **********\n");printf("**********     0.ExitContact     **********\n");printf("*******************************************\n");
}
int main()
{int input = 0;Contact con;//初始化通讯录InitContact(&con);//打印菜单do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case addContact:AddContact(&con);break;case delContact:DelContact(&con);break;case showContact:ShowContact(&con);break;case sehContact:SehContact(&con);break;case mofContact:MofContact(&con);break;case sortContact:SortContact(&con);break;case exitContact://销毁通讯录,进行动态空间的释放DestoryContact(&con);break;default:printf("输入错误,请重新输入!\n");break;}} while (input);return 0;
}

2.2contact.c函数各功能实现代码

#include"contact.h"//空间增容函数
void check_capacity(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){//通讯录已满,进行增容PeopInfo* str = (PeopInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeopInfo));if (str == NULL){perror("realloc");return;}pc->data = str;pc->capacity += INC_SZ;//总容量增加printf("空间增容成功,可以继续添加联系人\n");}
}//通过名字查找
int FindByName(const Contact* pc, char* Name)
{assert(pc);int i = 0;if (pc->sz == 0){printf("通讯录为空,无法查找!");return;}for (i = 0; i < pc->sz; i++){if (strcmp(Name, pc->data[i].Name) == 0)return i;}return -1;
}
//初始化这个通讯录,初始化为对应的值
void InitContact(Contact* pc)
{assert(pc);//为通讯录存放人的信息的结构体分配初始空间,并把里面数据直接//初始化为0,calloc函数很合适PeopInfo* str = (PeopInfo*)calloc(DEFAULT_SZ, sizeof(PeopInfo));if (str == NULL){perror("calloc");return;}pc->data = str;pc->sz = 0;pc->capacity = DEFAULT_SZ;
}//增加通讯录联系人
void AddContact(Contact* pc)
{assert(pc);check_capacity(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].Tele);printf("请输入联系人家庭住址:>");scanf("%s", pc->data[pc->sz].Addr);pc->sz++;
}
//删除指定联系人
void DelContact(Contact* pc)
{assert(pc);char Name[NAME_MAX] = { 0 };int i = 0;if (pc->sz == 0){printf("通讯录为空,无法删除!\n");return;}printf("请输入要删除的人的姓名:>");scanf("%s", Name);int pos = FindByName(pc, Name);if (pos == -1){printf("要删除的联系人不存在!\n");return;}for (i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除联系人成功!\n");
}//显示所有联系人
void ShowContact(const Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法显示!\n");return;}int i = 0;printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n","姓名","年龄","性别","电话号码","家庭住址");for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",pc->data[i].Name,pc->data[i].Age,pc->data[i].Sex,pc->data[i].Tele,pc->data[i].Addr);}
}//查找指定联系人
void SehContact(const Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法查找!\n");return;}char Name[NAME_MAX] = { 0 };printf("请输入要查找的人的姓名:>");scanf("%s", Name);int pos = FindByName(pc, Name);if (pos == -1){printf("要查找的联系人不存在!\n");return;}printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话号码", "家庭住址");printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",pc->data[pos].Name,pc->data[pos].Age,pc->data[pos].Sex,pc->data[pos].Tele,pc->data[pos].Addr);
}
//修改指点联系人的信息
void MofContact(Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法修改!\n");return;}char Name[NAME_MAX] = { 0 };printf("请输入要修改的人的姓名:>");scanf("%s", Name);int pos = FindByName(pc, Name);if (pos == -1){printf("要修改的联系人不存在!\n");return;}printf("请输入联系人姓名:>");scanf("%s", pc->data[pos].Name);printf("请输入联系人年龄:>");scanf("%d", &pc->data[pos].Age);printf("请输入联系人性别:>");scanf("%s", pc->data[pos].Sex);printf("请输入联系人电话号码:>");scanf("%s", pc->data[pos].Tele);printf("请输入联系人家庭住址:>");scanf("%s", pc->data[pos].Addr);
}//对所有联系人按姓名进行排序
void SortContact(const Contact* pc)
{assert(pc);int i = 0;int j = 0;for (i = 0; i < pc->sz; i++){for (j = i; j < pc->sz; j++){if (strcmp(pc->data[i].Name, pc->data[j].Name) > 0){PeopInfo temp[] = { 0 };temp[0] = pc->data[i];pc->data[i] = pc->data[j];pc->data[j] = temp[0];}}}ShowContact(pc);//显示一下排列结果
}//销毁通讯录,释放动态内存空间
void DestoryContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;pc = NULL;printf("通讯录已销毁\n");
}

2.3contact.h实现通讯录所需要的头文件代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<errno.h>#define DEFAULT_SZ 3//初始通讯录内存放的联系人个数
#define INC_SZ 2//每次增容的空间
#define NAME_MAX  20
#define SEX_MAX  5
#define TELE_MAX 12
#define ADDR_MAX 30//创建一个结构体,用来存放人的信息
typedef struct PeopInfo
{char Name[NAME_MAX];int Age;char Sex[SEX_MAX];char Tele[TELE_MAX];char Addr[ADDR_MAX];
}PeopInfo;//创建通讯录,里面包含人的信息,通讯录原本空间大小,以及当前通讯录
//存放了多少人
typedef struct Contact
{PeopInfo* data;//不可以是数组了,如果是数组,这块空间就已经被开辟好了//不能在进行动态开辟,后续使用时变为了不可修改的左值,建议用指针int sz;//当前以存放人的信息的个数int capacity;//目前通讯录空间的容量
}Contact;//空间增容函数
void check_capacity(Contact* pc);//初始化这个通讯录,初始化为对应的值
void InitContact(Contact* pc);
//增加通讯录联系人
void AddContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//显示所有联系人
void ShowContact(const Contact* pc);
//通过名字查找
int FindByName(const Contact* pc, char* Name);
//查找指定联系人
void SehContact(const Contact* pc);
//修改指点联系人的信息
void MofContact(Contact* pc);
//对所有联系人按姓名进行排序
void SortContact(const Contact* pc);//销毁通讯录,释放动态内存空间
void DestoryContact(Contact* pc);

3.运行结果


这就是动态通讯录完整版,大家下期再见!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/160469.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW对多个同一类型控件进行操作

LabVIEW对多个同一类型控件进行操作 有时候LabVIEW要多多个同一类的控件进行操作&#xff0c;如对tab中某个page中所有String控件设为dissable。就可以用如下的方式。className是获取不同类型的控件。通过类型选择&#xff0c;可以选择所有的String控件&#xff0c;并可对特定…

prometheus + grafana进行服务器资源监控

在性能测试中&#xff0c;服务器资源是值得关注一项内容&#xff0c;目前&#xff0c;市面上已经有很多的服务器资 源监控方法和各种不同的监控工具&#xff0c;方便在各个项目中使用。 但是&#xff0c;在性能测试中&#xff0c;究竟哪些指标值得被关注呢&#xff1f; 监控有…

从零开始制作一个割草机器人

项目背景 为啥要做一个割草机器人呢&#xff1f;&#xff08;个人因素&#xff1a;我梦想就是做一款人形机器人保护人类&#xff0c;解放人类&#xff09; 基础准备&#xff1a;我们公司本身做过高精度&#xff0c;基于高精度的技术扩展到农机自动化驾驶。目前可以实现AB线拖…

0003Java安卓程序设计-springboot基于Android的学习生活交流APP

文章目录 **摘** **要**目 录系统设计开发环境 编程技术交流、源码分享、模板分享、网课教程 &#x1f427;裙&#xff1a;776871563 摘 要 网络的广泛应用给生活带来了十分的便利。所以把学习生活交流管理与现在网络相结合&#xff0c;利用java技术建设学习生活交流APP&…

【算法】昂贵的聘礼(dijkstra算法)

题目 年轻的探险家来到了一个印第安部落里。 在那里他和酋长的女儿相爱了&#xff0c;于是便向酋长去求亲。 酋长要他用 10000 个金币作为聘礼才答应把女儿嫁给他。 探险家拿不出这么多金币&#xff0c;便请求酋长降低要求。 酋长说&#xff1a;”嗯&#xff0c;如果你能够替我…

云智慧联合北航提出智能运维(AIOps)大语言模型及评测基准

随着各行业数字化转型需求的不断提高&#xff0c;人工智能、云计算、大数据等新技术的应用已不仅仅是一个趋势。各行业企业和组织纷纷投入大量资源&#xff0c;以满足日益挑剔的市场需求&#xff0c;追求可持续性和竞争力&#xff0c;这也让运维行业迎来了前所未有的挑战和机遇…

MacOS安装git

文章目录 通过Xcode Command Lines Tool安装(推荐)终端直接运行git命令根据流程安装先安装Command Lines Tool后再安装git 官网下载二进制文件进行安装官方国外源下载二进制文件(不推荐)国内镜像下载二进制文件(推荐)安装git 通过Xcode Command Lines Tool安装(推荐) 简单来讲C…

vivado布局分析

1、高亮显示布局 1. 在“ Netlist ” &#xff08; 网表 &#xff09; 窗口中 &#xff0c; 选择要分析的层级。 2. 从弹出菜单中 &#xff0c; 选择“ Highlight Leaf Cells ” → “ Select a color ” &#xff08; 高亮叶节点单元 > 选择颜色 &#xff09; 。 3. …

Docker DeskTop安装与启动(Windows版本)

一、官网下载Docker安装包 Docker官网如下&#xff1a; Docker官网不同操作系统下载页面https://docs.docker.com/desktop/install/windows-install/ 二、安装Docker DeskTop 2.1 双击 Docker Installer.exe 以运行安装程序 2.2 安装操作 默认勾选&#xff0c;具体操作如下…

【React】【react-globe.gl】3D Objects效果

目录 想要实现的效果实现过程踩坑安装依赖引入页面 想要实现的效果 示例地址 实现过程 踩坑 示例是通过script引入的依赖&#xff0c;但本人需要在react项目中实现该效果。按照react-globe.gl官方方法引入总是报错 Cant import the named export AmbientLight from non EcmaS…

玩转AIGC:如何选择最佳的Prompt提示词?

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

rust入门基础案例:猜数字游戏

案例出处是《Rust权威指南》&#xff0c;书中有更加详细的解释。从这个例子中&#xff0c;我们可以了解到 rust 的两个操作&#xff1a; 如何从控制台读取用户输入rust 如何生成随机数 代码格式化 编译器可在保存时对代码做格式化处理&#xff0c;底层调用 rustfmt 来实现&a…