动态内存管理改造简易通讯录

news2024/11/28 11:47:49

动态通讯录

本章内容基于上章内容实现,具体情况若有不清楚,请先查看上一篇文章。
动态通讯录实现了,动态开辟,如果存放满了,再开辟空间进行存储,相对静态更方便一些。

动态通讯录需要改造的地方

我们基于静态通讯录之上,来改造一下实现动态通讯录
需要改造的地方有:
结构体的改造
初始化函数
添加函数
退出通讯录

结构体的改造

静态的结构体是data是max也就是100。

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct Contact
{
	PeoInfo data[MAX];//存放成员数据
	int sz;//记录当前通讯录人数
}Contact;

Contact结构体中data数组是限定的,也就是100个。

动态通讯录的结构体代码如下:

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;
typedef struct Contact
{
	PeoInfo* data;//存放成员数据
	int sz;//记录当前通讯录人数
	int capacity;//记录当前通讯录容量
}Contact;

在静态的基础之上,我们改动了data从数组改编成了指针指向的是动态内存开辟的PeoInfo,以及多了一个参数capacity来记录当前通讯录容量。

改造初始化函数

静态的初始化函数是这样的

void InitContact(Contact* pc)
{
	assert(pc);

	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
}

直接把data成员里面全部赋值为0。

void InitContact(Contact* pc)
{
	assert(pc);

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(pc->capacity,sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
}

动态我们开辟一块内存用来存放PeoInfo的信息,而他的地址则让data指针指向即可,我们用if语句查看是否data指针为空,为空则提示一下calloc函数出错。

改造添加函数

添加函数与静态的不同则是通讯录不会再满了,因为我们满了我们会动态在开辟空间即可。

void ADDContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法增加\n");
		return;
	}
	//增加信息
	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++;
	printf("添加联系人成功!\n");
}

上面是静态的添加函数,接下来看一下动态的添加函数。

void ADDContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += DEFAULT_INC;
			printf("增加联系人空间成功\n");
		}
		else
		{
			perror("ADDContact->realloc");
		}
	}
	//增加信息
	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++;
	printf("添加联系人成功!\n");
}

我们首先判断通讯录由动态开辟的空间是否已满,满了则开辟新的空间,用realloc函数开辟即可,之后赋给PeoInfo类型的ptr指针。如果该指针不为空,那么再把ptr指针赋给data指针,之后让通讯录容量+2,在这里是为了方便测试,所以只加2,最后用printf函数提醒一下增加联系人空间成功,否则则提醒一下realloc函数出错。之后就可以正常添加信息。增加通讯录容量也可以单独封装成一个函数,感兴趣的话可以尝试一下。

改造退出通讯录

动态开辟空间在程序结束时都要释放出去,防止有不可预料的结果产生,所以退出通讯录也要稍微 改造一下,静态直接退出即可不需要函数,所以我们直接看动态的退出通讯录。

void DestoryContact(Contact* pc)
{
	free(pc->data);//释放动态内存空间
	pc->data = NULL;//赋为空指针
	pc->sz = 0;//释放完人数当然为0
	pc->capacity = 0;//释放完,通讯录容量也自然为0
}

这个十分简单,释放掉动态空间的地址,然后把该指针赋值为空指针,然后sz为零,capacity为零即可。

改造后的全部代码

为大家奉上完整的代码,方便参考调试。

test.c

#define  _CRT_SECURE_NO_WARNINGS
#include"contact.h"
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	EMPTY
};
void menu();
int main()
{
	int input = 0;
	Contact con;
	InitContact(&con);
	do
	{
		menu();
		printf("请输入你想选择的操作:");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT:
			DestoryContact(&con);
			printf("退出通讯录成功");
			break;
		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:
			SortContact(&con);
			break;
		case EMPTY:
			InitContact(&con);
			printf("清空通讯录成功\n");
			break;
		default:
			printf("输入错误\n");
			break;
		}


	} while (input);
	return 0;
}

contact.c

#define  _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{
	printf("*****************************\n");
	printf("*****0.EXIT****1.ADD*********\n");
	printf("*****2.DEL*****3.SEARCH******\n");
	printf("*****4.MODIFY**5.SHOW********\n");
	printf("*****6.SORT****7.EMPTY*******\n");
}
void InitContact(Contact* pc)
{
	assert(pc);

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(pc->capacity,sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
}
//void CheckCapacity(Contact* pc)
//{
//	if (pc->sz == pc->capacity)
//	{
//		PeoInfo* ptr = realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
//		if (ptr != NULL)
//		{
//			pc->sz = ptr;
//			pc->capacity += DEFAULT_INC;
//			printf("增加联系人空间成功\n");
//		}
//		else
//		{
//			perror("ADDContact->realloc");
//		}
//	}
//}
void ADDContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += DEFAULT_INC;
			printf("增加联系人空间成功\n");
		}
		else
		{
			perror("ADDContact->realloc");
		}
	}
	//增加信息
	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++;
	printf("添加联系人成功!\n");
}

void SHOWContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需打印\n");
		return;
	}
	int i = 0;
	//名字  年龄  性别  电话    地址
	//xxx   xxx  xxx  xxx     xxx
	printf("%-20s%-10s%-10s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每个人的信息
		printf("%-20s%-10d%-10s%-12s%-30s\n",
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}
int FindByName(Contact* pc, char* name)
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void DELContact(Contact* pc)
{
	char name[NAME_MAX];
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,不可删除\n");
		return;
	}
	printf("请输入你想删除的联系人:");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		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");
}
void SearchContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入想查找的联系人");
	scanf("%s", &name);
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在!\n");
		return;
	}
	printf("%-20s%-10s%-10s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("%-20s%-10d%-10s%-12s%-30s\n",
		pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}
void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入想修改的联系人");
	scanf("%s", &name);
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在!\n");
		return;
	}
	printf("请输入姓名:");
	scanf("%s", pc->data[ret].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[ret].age));
	printf("请输入性别:");
	scanf("%s", pc->data[ret].sex);
	printf("请输入电话号码:");
	scanf("%s", pc->data[ret].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[ret].addr);
	printf("修改联系人成功!\n");
}
int compare_name(const void* base, const void* src)
{
	return strcmp(((PeoInfo*)base)->name, ((PeoInfo*)src)->name);
}
int compare_age(const void* base, const void* src)
{
	return (((PeoInfo*)base)->age - ((PeoInfo*)src)->age);
}
void SortContact(Contact* pc)
{
	int ret = 0;
	printf("1按名字排序,2按年龄排序\n");
	scanf("%d", &ret);
	if (ret == 1)
	{
		qsort(pc->data, pc->sz, sizeof(PeoInfo), compare_name);
		SHOWContact(pc);
		printf("名字排序成功\n");
	}
	else if (ret == 2)
	{
		qsort(pc->data, pc->sz, sizeof(PeoInfo), compare_age);
		SHOWContact(pc);
		printf("年龄排序成功\n");
	}
	else
	{
		printf("选择错误,返回操作");
	}

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

contact.h

#define  _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 10
#define TELE_MAX 12
#define ADDR_MAX 30

#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

//typedef struct Contact
//{
//	PeoInfo data[MAX];//存放成员数据
//	int sz;//记录当前通讯录人数
//}Contact;
typedef struct Contact
{
	PeoInfo* data;//存放成员数据
	int sz;//记录当前通讯录人数
	int capacity;//记录当前通讯录容量
}Contact;
void menu();
void InitContact(Contact* pc);
void ADDContact(Contact* pc);
void SHOWContact(const Contact* pc);
void DELContact(Contact* pc);
void SearchContact(Contact* pc);
void ModifyContact(Contact* pc);
void SortContact(Contact* pc);
void DestoryContact(Contact* pc);

最后各位看客老爷万福金安。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python--比较运算符

比较运算符 特别注意&#xff1a;当我们使用比较运算符对两个变量进行比较时&#xff0c;其返回一个布尔类型的值。 案例&#xff1a;两个数大小的比较 num1 10 num2 20 print(num1 > num2) # False print(num1 < num2) # True print(num1 > num2) # False print…

使用免费云服务器体验

免费的才是最贵的 谈谈使用【三*丰*云*免*费*服务器】的超级后悔体验 你以为开通了就永久免费了&#xff1f;怎么可能&#xff01;&#xff01;&#xff01; 使用方法 第一步&#xff1a;注册&#xff0c;实名认证 实名认证收费0.7 此时可以使用24小时&#xff0c;到期自动…

AI影像修复及图像超分辨率

AI图像修复软件主要包含人脸修复、图像超分等功能。人脸修复功能主要对图像上的人脸进行识别和修复&#xff0c;从模糊、缺损、噪声图像中恢复高质量人脸图像。图像超分功能主要对图像进行超分辨率重建&#xff0c;将低分辨率图像处理为高分辨率图像。 链接&#xff1a;https:…

Linux:基础命令

Linux&#xff1a;基础命令 0. Linux的目录结构1. Linux命令基础格式2. ls命令2.1 隐藏文件、文件夹 3. 相对和绝对路径3.1 特殊路径符 4. mkdir命令4.1 mkdir -p 选项 5. touch 创建文件6. cat命令 查看文件内容 0. Linux的目录结构 /&#xff0c;根目录是最顶级的目录了Linux…

【java学习—七】关键字super(32)

文章目录 1. 功能2. 代码中理解3. super调用父类构造器3.1. 结论一证明3.2. 结论二证明 4. this和super的区别 1. 功能 在 Java 类中使用 super 来调用父类中的指定操作&#xff1a; &#xff08;1&#xff09;super 可用于访问父类中定义的属性 &#xff08;2&#xff09;sup…

unity的脚本执行顺序问题

当一个物体同时挂载有多个脚本时&#xff0c;谁会先执行呢&#xff1f; 猜想&#xff1a;Test2在Test1的上面应该会先执行吧&#xff01; 结果&#xff1a;Test1先执行 如果你想要某一个脚本先执行&#xff0c;可以使用Awake方法 执行顺序 是先把所以脚本的Awake执行完&a…

【Transformer系列】深入浅出理解ViT(Vision Transformer)网络模型

一、参考资料 极智AI | 详解 ViT 算法实现 MobileViT模型简介 ECCV 2022丨力压苹果MobileViT&#xff0c;这个轻量级视觉模型新架构火了 ECCV 2022丨轻量级模型架构火了&#xff0c;力压苹果MobileViT&#xff08;附代码和论文下载&#xff09; 再读VIT&#xff0c;还有多少细…

学习笔记---超基础+详细+新手的顺序表~~

目录 1.顺序表的前言 1.1 顺序表--->通讯录&#x1f4c7; 1.2 数据结构的相关概念&#x1f3c7; 1.2.1 什么是数据结构 1.2.1 为什么需要数据结构 2. 顺序表概念及分类 2.1 顺序表的概念&#x1f419; 2.2 顺序表的分类&#x1f42b; 2.2.1 顺序表和数组的区别 2.…

c++ 学习之多态

来看代码 我们来看看早绑定的代码 #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std;class Animal { public:void speak(){cout << "动物在说话 " << endl;} }; class Cat : public Animal { public:void speak() {cout…

android studio检测不到真机

我的情况是&#xff1a; 以前能检测到&#xff0c;有一天我使用无线调试&#xff0c;发现调试有问题&#xff0c;想改为USB调试&#xff0c;但是半天没反应&#xff0c;我就点了手机上的撤销USB调试授权&#xff0c;然后就G了。 解决办法&#xff1a; 我这个情况比较简单&…

LD链接脚本

1.LD链接脚本的简介 LD链接脚本的概念 LD链接器脚本在完整程序编译流程中的链接过程使用。LD链接器脚本定义了程序各个程序段的存储分布&#xff0c;描述链接器如何将这些目标文件.o文件链接成一个输出可执行文件LD链接器脚本与CPU的种类、MCU的内部存储器分布有关。 LD链接…

华为---企业WLAN组网基本配置示例---AC+AP组网

ACAP组网所需的物理条件 1、无线AP---收发无线信号&#xff1b; 2、无线控制器(AC)---用来控制管理多个AP&#xff1b; 3、PoE交换机---能给AP实现网络连接和供电的交换机&#xff1b; 4、授权&#xff1a;默认AC管理的AP数量有限&#xff0c;买授权才能管控更多AP。 WLAN创建…

思维模型 峰终定律

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。 1 峰-终定律的应用 1.1 迪士尼游乐园 迪士尼乐园采用了多种策略来创造令人难忘的体验&#xff0c;从而遵循峰终定律的原则。具体如下&#xff1a; 迪士尼乐园的入口设计和服务体验&…

E047-论坛漏洞分析及利用-针对Wordpress论坛进行信息收集与漏洞扫描的探索

任务实施: E047-论坛漏洞分析及利用-针对Wordpress论坛进行信息收集与漏洞扫描的探索 任务环境说明&#xff1a; 服务器场景&#xff1a;p9_kali-6&#xff08;用户名&#xff1a;root&#xff1b;密码&#xff1a;toor&#xff09; 服务器场景操作系统&#xff1a;Kali Li…

零代码编程:用ChatGPT批量下载谷歌podcast上的播客音频

谷歌podcast有很多播客音频&#xff0c;如何批量下载到电脑呢&#xff1f; 以这个播客为例&#xff1a; https://podcasts.google.com/feed/aHR0cHM6Ly9oYWRhcnNoZW1lc2guY29tL2ZlZWQvcG9kY2FzdC8?saX&ved0CAkQlvsGahcKEwi4uauWsvKBAxUAAAAAHQAAAAAQAg 查看网页源代码&a…

【LeetCode刷题(数据结构与算法)】:二叉树的后序遍历

给你一棵二叉树的根节点root 返回其节点值的后序遍历 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[3,2,1] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; 输入&#xff1a;root [1] 输出&#xff1a;[1]…

智慧公厕厂家,解读智慧厕所的全面功能应用

近年来&#xff0c;随着城市化进程的加速&#xff0c;智慧公厕的建设与发展成为了城市管理的重要一环。作为城市的门面和城市基础设施的重要组成部分&#xff0c;智慧公厕不仅能够满足人们基本的生理需求&#xff0c;更能提升城市形象和居民生活品质。那么&#xff0c;智慧公厕…

堆专题4 堆排序

题目&#xff1a; 样例&#xff1a; 输入 5 2 8 5 1 3 输出 1 2 3 5 8 思路&#xff1a; 由题意&#xff0c;堆的排序&#xff0c;就是结合向下或向上调整的方式&#xff0c;调整堆顺序&#xff0c;全部的各个部分都变为 顶堆形式。不同的是&#xff0c;由于我们是顶堆原理&a…

学信息系统项目管理师第4版系列28_组织级项目管理和量化项目管理

1. OPM 1.1. 旨在确保组织开展正确项目并合适地分配关键资源 1.1.1. 有助于确保组织的各个层级都了解组织的战略愿景、实现愿景的措施、组织目标以及可交付成果 1.2. 业务评估是建立OPM框架的必要组件 1.3. OPM3 是组织级项目管理成熟度模型&#xff0c;可用于评估组织项目…

华为OD机考算法题:开心消消乐

题目部分 题目开心消消乐难度易题目说明给定一个 N 行 M 列的二维矩阵&#xff0c;矩阵中每个位置的数字取值为 0 或 1&#xff0c;矩阵示例如&#xff1a; 1 1 0 0 0 0 0 1 0 0 1 1 1 1 1 1 现需要将矩阵中所有的 1 进行反转为 0&#xff0c;规则如下&#xff1a; 1) 当点击一…