动态内存管理—C语言通讯录
目录
一,动态内存函数的介绍
1.1 malloc和free
1.2 calloc
1.3 realloc
1.4C/C++程序的内存开辟
二,通讯录管理系统
动态内存函数的介绍
malloc
free
calloc
realloc
一,动态内存函数的介绍
1.1 malloc和free
void* malloc ( size_t size );
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。如果开辟成功,则返回一个指向开辟好空间的指针。如果开辟失败,则返回一个NULL 指针,因此 malloc的返回值一定要做检查。返回值的类型是 void* ,所以 malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。如果参数 size 为 0 , malloc的行为是标准是未定义的,取决于编译器。
void free ( void* ptr );
free 函数用来释放动态开辟的内存。如果参数 ptr 指向的空间不是动态开辟的,那 free 函数的行为是未定义的。如果参数 ptr 是 NULL 指针,则函数什么事都不做。
1.2 calloc
void* calloc ( size_t num , size_t size );
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为 0 。与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全 0 。
例如:

1.3 realloc
realloc 函数的出现让动态内存管理更加灵活。有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存,我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。
void* realloc ( void* ptr , size_t size );
ptr 是要调整的内存地址size 调整之后新大小返回值为调整之后的内存起始位置。这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新 的空间。realloc 在调整内存空间的是存在两种情况情况 1 :原有空间之后有足够大的空间情况 2 :原有空间之后没有足够大的空间情况 1当是情况 1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。情况 2当是情况 2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。

将刚刚malloc的空间扩大了2呗,当然指针在给p1之前是需要判断是否开辟成功的,如果没有足够的空间去开辟的话,realloc是会返回NULL指针的,如果用p1去接受,那么就会找不到原来的地址进而导致内存泄漏。
1.4C/C++程序的内存开辟

二,通讯录管理系统
头文件:
contact.h
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
//通讯录信息包含姓名,年龄,性别,电话,住址
typedef struct PeoInfo
{char name[20];int age;char sex[10];char tele[12];char addr[30];
}PeoInfo;
typedef struct Contact
{//每个人的信息PeoInfo* data;//当天通讯录存储的个数int count;//当前通讯录的容量int capacity;
}Contact;//销毁通讯录
void DestoryContact(Contact* pc);
//初始化通讯录
void InitContact(Contact* pc);//增加通讯录信息
void AddContact(Contact* pc);//打印通讯录的内容
void ShowContact(Contact* pc);
//删除通讯录的内容
void DelContact(Contact* pc);
//查找通讯录的信息
void SearchContact(Contact* pc);
//修改通讯录的信息
void ModifyContact(Contact* pc);
//排序通讯录的内容
void SortContact(Contact* pc); contact.c文件
#include"contact.h"//初始化通讯录
void InitContact(Contact* pc)
{//断言,pc不为空assert(pc);//初始时我们给通讯录两个大小的空间Contact* temp = (PeoInfo*)calloc(2, sizeof(PeoInfo));//如果开辟成功这将if (temp){pc->data = temp;pc->capacity = 2;pc->count = 0;}
}//检测通讯录容量
void Checkcapacity(Contact* pc)
{//如果当前容量等于我们的存放信息的个数那么我们就扩容if (pc->capacity == pc->count){Contact* temp = (Contact*)realloc(pc->data, sizeof(PeoInfo) * 4);if (temp){pc = temp;//每次增容成功会都要增加capacity的值pc->capacity = pc->capacity + 4;printf("增容成功\n");}}
}//增加联系人
void AddContact(Contact* pc)
{assert(pc);//判断通讯录是否已满Checkcapacity(pc);//添加信息printf("请输入姓名:>");scanf("%s", pc->data[pc->count].name);printf("请输入年龄:>");scanf("%d", &pc->data[pc->count].age);printf("请输入性别:>");scanf("%s", pc->data[pc->count].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->count].tele);printf("请输入住址:>");scanf("%s", pc->data[pc->count].addr);//每次添加联系人之后要将count+1pc->count++;printf("添加成功\n");
}//销毁通讯录
void DestoryContact(Contact* pc)
{//释放我们申请的空间free(pc->data);pc->data = NULL;
}//展示通讯录的信息
void ShowContact(Contact* pc)
{assert(pc);int i = 0;printf("%-10s%-10s%-10s%-12s%-10s\n", "姓名", "年龄", "性别", "电话", "住址");for (i = 0; i < pc->count; i++){printf("%-10s%-10d%-10s%-20s%-15s", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);printf("\n");}}//查找通讯录里面是否有这个 不考虑重名问题
int find_by_name(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->count; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}//删除通讯录中某个人的信息
void DelContact(Contact* pc)
{assert(pc);printf("请输入要删除人的姓名:>");char name[20] = { 0 };//如果通讯录中没有信息if (pc->count == 0){printf("通讯录中没有信息可删除\n");return;}scanf("%s", name);//查找信息int pos = find_by_name(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}//删除信息int i = 0;for (i = pos; i <= pc->count - 1; i++){pc->data[pos] = pc->data[pos + 1];}pc->count--;printf("删除成功\n");
}//查找通讯录中的某个人
void SearchContact(Contact* pc)
{assert(pc);if (pc->count == 0){printf("通讯录中没有信息可删除\n");return;}char name[20] = { 0 };printf("请输入你要查找人的名字:>");scanf("%s", name);int pos = find_by_name(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}printf("要查找人的信息如下:>\n");printf("%-10s%-10s%-10s%-12s%-10s\n", "姓名", "年龄", "性别", "电话", "住址");printf("%-10s%-10d%-10s%-20s%-15s", pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);printf("\n");
}//修改通讯录中某个人信息
void ModifyContact(Contact* pc)
{assert(pc);if (pc->count == 0){printf("通讯录中没有信息可修改\n");return;}char name[20] = { 0 };//查找printf("请输入你要修改信息人的名子:>");scanf("%s", name);int pos = find_by_name(pc, name);if (pos == -1){printf("要修改的人的信息不存在\n");return;}//修改printf("请输入你要修改的内容:\n");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);printf("修改成功\n");
}//给qsort函数的比较函数
int cmp_by_name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
//排序我们的通讯录,按照名字排序
void SortContact(Contact* pc)
{assert(pc);qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_by_name);printf("排序成功\n");
} test.c
#include "contact.h"void menu()
{printf("**************************************\n");printf("**************************************\n");printf("******* 1.add 2.Del **********\n");printf("******* 3.search 4.modify **********\n");printf("******* 5.show 6.sort **********\n");printf("******* 0.exit **********\n");printf("**************************************\n");printf("**************************************\n");
}
int main()
{int input = 0;Contact con;InitContact(&con);do{ //打印菜单做提示menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:AddContact(&con);break;case 2:DelContact(&con);break;case 3:SearchContact(&con);break;case 4:ModifyContact(&con);break;case 5:ShowContact(&con);break;case 6:SortContact(&con);break;case 0:printf("退出程序\n");DestoryContact(&con);break;default:printf("选择错误请重新选择:>");break;}} while (input);return 0;
} 
相关文章:
动态内存管理—C语言通讯录
目录 一,动态内存函数的介绍 1.1 malloc和free 1.2 calloc 1.3 realloc 1.4C/C程序的内存开辟 二,通讯录管理系统 动态内存函数的介绍 malloc free calloc realloc 一,动态内存函数的介绍 1.1 malloc和free void* malloc (…...
美光EMMC芯片丝印型号查询 8LK17/D9PSK, OXA17/JY997
问题说明 最近在使用美光EMMC的时候,发现通过芯片丝印查询不到 芯片的规格说明书; 经过查阅资料,发现美光的EMMC芯片 “由于空间限制,FBGA 封装组件具有与部件号不同的缩写部件标记”,需要通过官网查询丝印的FBGA cod…...
win32-鼠标消息、键盘消息、计时器消息、菜单资源
承接前文: win32窗口编程windows 开发基础win32-注册窗口类、创建窗口win32-显示窗口、消息循环、消息队列 本文目录 键盘消息键盘消息的分类WM_CHAR 字符消息 鼠标消息鼠标消息附带信息 定时器消息 WM_TIMER创建销毁定时器 菜单资源资源相关菜单资源使用命令消息的…...
springboot项目部署到linux服务器
springboot后端 修改前 修改后 vue前端 修改前 将地址中的 localhost改为 ip 重新生成war包 war上传到linux的tomcat的webapps下 其他环境配置和macOS大差不差 Tomcat安装使用与部署Web项目的三种方法_tomcat部署web项目-CSDN博客...
MagicLens:新一代图像搜索技术和产品形态
MagicLens:Self-Supervised Image Retrieval with Open-Ended Instructions MagicLens: 自监督图像检索与开放式指令 作者:Kai Zhang, Yi Luan, Hexiang Hu, Kenton Lee, Siyuan Qiao, Wenhu …...
[9] CUDA性能测量与错误处理
CUDA性能测量与错误处理 讨论如何通过CUDA事件来测量它的性能如何通过CUDA代码进行调试 1.测量CUDA程序的性能 1.1 CUDA事件 CPU端的计时器可能无法给出正确的内核执行时间CUDA事件等于是在你的CUDA应用运行的特定时刻被记录的时间戳,通过使用CUDA事件API&#…...
Java学习四
Random 随机数 数组 静态初始化数组 数组在计算机中的基本原理 数组的访问 什么是遍历 数组的动态初始化 动态初始化数组元素默认值规则 Java内存分配介绍 数组在计算机中的执行原理 使用数组时常见的一个问题 案例求数组元素最大值 public class Test1 {public static void ma…...
Vue 父组件使用refs来直接访问和修改子组件的属性或调用子组件的方法
步骤 1: 在子组件中定义要被修改的属性或方法 首先,在子组件中定义你想要父组件能够修改或调用的属性或方法。例如,我们有一个名为MyChildComponent的子组件,它有一个名为childData的数据属性和一个名为updateData的方法。 // 子组件 MyChi…...
范罗士、希喂、安德迈爆款宠物空气净化器哪款好?深度对比测评
作为一名深受养猫过敏困扰的铲屎官,我经常提醒新手铲屎官重视家里的空气环境。宠物的浮毛和皮屑不仅会引发过敏,还可能传播细菌和病毒。很多人以为普通空气净化器能解决问题,但这些产品并未针对宠物家庭的特殊需求。经过多次研究和测试&#…...
SAP OBYC自动记账 详解
在MM模块的许多操作都能实现在FI模块自动过账,如PO收货、发票验证、工单发料、向生产车间发料等等。不用说,一定需要在IMG中进行配置才可以实现自动处理。但SAP实现的这种自动配置的机制是怎样的呢?其实也并不复杂,让我们先以一种最简单的情况来了解实现原理和实现流程,然…...
《NoSQL数据库技术与应用》 MongoDB副本集
《NoSQL数据库技术与应用》 教学设计 课程名称:NoSQL数据库技术与应用 授课年级: 20xx年级 授课学期: 20xx学年第一学期 教师姓名: 某某老师 2020年5月6日 课题 名称 第4章 MongoDB副本集 计划学时 8课时 内容 分析 独立模式可…...
Flutter 中的 DropdownButtonFormField 小部件:全面指南
Flutter 中的 DropdownButtonFormField 小部件:全面指南 在Flutter中,DropdownButtonFormField是一个特殊的表单字段小部件,它结合了下拉选择框(DropdownButton)和表单字段(FormField)的功能。…...
哈希算法教程(个人总结版)
背景 哈希算法(Hash Algorithm)是一种将任意长度的输入(也称为消息)转换为固定长度的输出(也称为哈希值、散列值、摘要)的算法。哈希算法在计算机科学中有着广泛的应用,包括数据存储、数据检索…...
Nocobase快速上手 -第一个collection
本文记录Nocobase中如何创建collection,以及如何将collection展示到页面中,并且配置CRUD相应的操作. Collection 在NocoBase中,collection(集合)是用来组织和存储各种数据的容器,如订单、产品、用户、评论…...
吴恩达2022机器学习专项课程C2W2:2.19 sigmoid函数的替代方案 2.20如何选择激活函数 2.21 激活函数的重要性
这里写目录标题 引言sigmoid激活函数的局限1.回顾需求案例2.ReLU激活函数 常用的激活函数1.线性激活函数的解释 如何选择激活函数?1.选择输出层的激活函数2.选择隐藏层的激活函数 选择激活函数的总结1.输出层总结2.隐藏层总结3.TensorFlow设置激活函数 激活函数多样…...
循序渐进Docker Compose
文章目录 1.概述1.1 Docker Compose 定义1.2 Docker Compose背景1.3 Docker Compose核心概念 2.安装2.1 Official Repos2.2 Manual Installation2.3 v1.x 兼容性 3. YAML 配置说明3.1 Services3.2 Volumes & Networks 4. 解析 Service4.1 Pulling一个Image4.2 Building一个…...
怎样查看JavaScript中没有输出结果的数组值?
在JavaScript中,可以方便地定义和使用数组,对于已经定义的数组,怎样查看其值呢? 看下面的示例,并运行它。 上面的示例中,标签不完整,请补充完整再试运行。你知道少了什么标签么? 注…...
强化学习学习笔记-李宏毅
Policy Gradient actorenvreward function,env和reward是不能控制的,唯一可以变的是actor,Policy π \pi π是一个网络,参数为 θ \theta θ,输入是当前的观察,输出是采取的行为,例如游戏中输…...
吴恩达深度学习笔记:超 参 数 调 试 、 Batch 正 则 化 和 程 序 框 架(Hyperparameter tuning)3.8-3.9
目录 第二门课: 改善深层神经网络:超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第三周: 超 参 数 调 试 、 Batch 正 则 化 和 程 序 框 架(Hyperparameter …...
SQL 语言:数据控制
文章目录 概述授权(GRANT)销权(REVOKE)总结 概述 SQL语言中的数据控制权限分配是数据库管理的重要组成部分,它涉及到如何合理地为用户分配对数据库资源的访问和使用权限。 权限类型:在SQL中,权限主要分为…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
