通讯录2.0(动态内存管理)

news/2024/11/25 5:51:27/

个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C/C++】
在这里插入图片描述

哈喽!今天再次来到通讯录这里,不过是给它进行了一次小小的升级(把动态内存的知识给它嵌入到里面去)。
详情请点击查看:通讯录1.0
之前只是给大家简单的实现了通讯录的增删查改。里面存在的缺陷是肯定有的。
1.0版本的通讯录

struct Contact
{PeoInfo data[1000];int sz;
};

这种实现PeoInfo data[1000];是我们已经把通讯录里面能存放多少人的信息一次性就固定好了,也就是一旦创建了这个数组,就无法改变。不管通讯录里面有几个人的信息,空间已经开辟好了,但实际上并没有那么多人的信息,肯定会造成内存空间的不合理运用。当然如果朋友比较多,想存放超过1000个人的信息,比如想存放2000、甚至5000个人的信息。我们可以发现内存空间已经开辟好了,只能存放1000个人的信息,如果想多存几个人的信息是做不到的
那现在我们把它改为可以动态增长的通讯录版本

起初默认可以存放3个人的信息,
当发现当前通讯录满的时候,我们进行扩容,每次增加2个空间
此时我们的空间是可以动态增长的(对空间的利用也更加友好一些)

请看新版通讯录:
test.c

#define _CRT_SECURE_NO_WARNINGS 1#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"void menu()
{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");
}int main()
{int input = 0;//循环开始前应该提前把通讯录创建好struct Contact con;//con就是通讯录,里面包含data指针和size,capacity//初始化通讯录InitContact(&con);do{menu();//菜单printf("请选择:>");scanf("%d", &input);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 EXIT://退出之前销毁通讯录-释放动态开辟的内存。DestroyContact(&con);printf("退出通讯录");break;default:printf("选择错误,请重新选择:>");break;}} while (input);return 0;
}

contact.h

#define _CRT_SECURE_NO_WARNINGS 1#define _CRT_SECURE_NO_WARNINGS 1
//#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#define DffAULT_SZ 3#include<stdio.h>
#include<string.h>
#include<stdlib.h>enum Option//增加代码可读性
{EXIT,//0ADD, //1DEL, //2SEARCH,MODIFY,SHOW,SORT
};typedef struct PeoInfo
{char name[MAX_NAME];int age;char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInfo;//通讯录类型
typedef struct Contact
{struct PeoInfo *data;int size;//记录当前已经有的元素个数int capacity;//当前通讯录最大容量
}Contact;//声明函数
//通讯录初始化
void InitContact(struct Contact* ps);//增加一个信息到通讯录
void AddContact(struct Contact* ps);//打印通讯录中的信息
void ShowContact(const struct Contact* ps);//删除指定的联系人
void DelContact(struct Contact* ps);//查找指定人的信息
void SearchContact(const struct Contact* ps);//修改指定联系人
void ModifyContact(struct Contact* ps);void DestroyContact(Contact* ps);

contact.c

#define _CRT_SECURE_NO_WARNINGS 1#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"void InitContact(struct Contact* ps)
{ps->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));if (ps->data == NULL){return;}ps->size = 0;ps->capacity = DffAULT_SZ;
}//检测容量
void CheckCapacity(struct Contact* ps)
{if (ps->size == ps->capacity)//等于就说明通讯录满了{//增容struct PeoInfo* ptr=realloc(ps->data, (ps->capacity + 2) * sizeof(PeoInfo));if (ptr != NULL){ps->data = ptr;ps->capacity += 2;printf("增容成功\n");}else{printf("增容失败\n");}}
}void AddContact(struct Contact* ps)
{//检测当前通讯录的容量//1.如果满了,就增加了空间//2.如果不满,啥事都不干CheckCapacity(ps);//增加数据printf("请输入名字:>");scanf("%s", ps->data[ps->size].name);printf("请输入年龄:>");scanf("%d", &ps->data[ps->size].age);printf("请输入性别:>");scanf("%s", ps->data[ps->size].sex);printf("请输入电话:>");scanf("%s", ps->data[ps->size].tele);printf("请输入地址:>");scanf("%s", ps->data[ps->size].addr);ps->size++;printf("添加成功\n");/*if (ps->size == MAX){printf("通讯录已满,无法增加\n");}else{printf("请输入名字:>");scanf("%s", ps->data[ps->size].name);printf("请输入年龄:>");scanf("%d", &ps->data[ps->size].age);printf("请输入性别:>");scanf("%s", ps->data[ps->size].sex);printf("请输入电话:>");scanf("%s", ps->data[ps->size].tele);printf("请输入地址:>");scanf("%s", ps->data[ps->size].addr);ps->size++;printf("添加成功\n");}*/
}void ShowContact(const struct Contact* ps)
{if (ps->size == 0){printf("通讯录为空\n");}else{int i = 0;//标题printf("%-15s\t%-4s\t%-s5\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");//数据for (i = 0; i < ps->size; i++){printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",ps->data[i].name,ps->data[i].age,ps->data[i].sex,ps->data[i].tele,ps->data[i].addr);}}
}static int FindByName(const struct Contact* ps, char name[MAX_NAME])
{int i = 0;for (i = 0; i < ps->size; i++){if (0 == strcmp(ps->data[i].name, name)){return i;}}return -1;//找不到的情况
}void DelContact(struct Contact* ps)
{char name[MAX_NAME];int pos = 0;printf("请输入要删除人的名字:>");scanf("%s", name);//1.查找要删除的人在什么位置pos = FindByName(ps, name);//找到了就返回名字所在的元素下标,找不到返回-1if (pos == -1){printf("要删除的人不存在\n");}else{int j = 0;for (j = pos; j < ps->size - 1; j++)//{ps->data[j] = ps->data[j + 1];}ps->size--;printf("删除成功\n");}//2.删除
}void SearchContact(const struct Contact* ps)
{int pos = 0;char name[MAX_NAME];printf("请输入要查找人的名字:>");scanf("%s", name);pos = FindByName(ps, name);if (pos == -1){printf("要查找的人不存在\n");}else{printf("%-15s\t%-4s\t%-s5\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址");//数据printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",ps->data[pos].name,ps->data[pos].age,ps->data[pos].sex,ps->data[pos].tele,ps->data[pos].addr);}
}void ModifyContact(struct Contact* ps)
{int pos = 0;char name[MAX_NAME];printf("请输入要修改人的名字:>");scanf("%s", name);pos = FindByName(ps, name);if (pos == -1){printf("要修改人的信息不存在");}else{printf("请输入名字:>");scanf("%s", ps->data[pos].name);printf("请输入年龄:>");scanf("%d", &ps->data[pos].age);printf("请输入性别:>");scanf("%s", ps->data[pos].sex);printf("请输入电话:>");scanf("%s", ps->data[pos].tele);printf("请输入地址:>");scanf("%s", ps->data[pos].addr);printf("修改完成\n");}
}void DestroyContact(Contact* ps)
{free(ps->data);ps->data = NULL;
}

就到这里了,再见啦!!!
在这里插入图片描述


http://www.ppmy.cn/news/22817.html

相关文章

C# 基础知识(二)_第一个入门程序

目录 C# 基础知识(二)_第一个入门程序 Hello World 代码分析 执行程序 C# 基础知识(二)_第一个入门程序 Hello World using System;namespace Notes {class Program{static void Main(string[] args){//第一个C#程序Console.WriteLine("Hello World!"); …

python GUI(Tkinter)

Tkinter简介 是python内置的标准GUI库&#xff0c;在安装python后&#xff0c;导入模块即可正常使用&#xff0c;Tk和Tkinter可在大多数的Unix&#xff0c;以及Windows和Macintosh系统上运行。 关于Tkinter的导入&#xff08;注意大小写&#xff09; 在2.x版本上&#xff0c…

第004天:APP在平板上的UI布局设计

当今是移动设备发展非常迅速的时代&#xff0c;不仅手机已经成为了生活必需品&#xff0c;就连平板电脑也变 得越来越普及。平板电脑和手机最大的区别就在于屏幕的大小&#xff0c;一般手机屏幕的大小会在3英寸 到6英寸之间&#xff0c;而一般平板电脑屏幕的大小会在7英寸到10英…

【青训营】软件开发流程

文章内容总结自&#xff1a;字节跳动青训营 软件开发流程 软件开发模型简介 传统瀑布模型 将流程视作为一条线&#xff1a; 完成需求分析后开发&#xff0c;开发完成后测试&#xff0c;测试完成后发布&#xff0c;发布完成后进行运维。这是最直观的一个模型&#xff0c;其流…

初阶C语言——函数【详解】(重点:函数的递归)

文章目录1.什么是函数2. 函数分类2.1 库函数&#xff1a;2.2 自定义函数3.函数的参数3.1 实际参数&#xff08;实参&#xff09;3.2 形式参数&#xff08;形参&#xff09;4. 函数的调用&#xff1a;4.1 传值调用4.2 传址调用4.3 练习5. 函数的嵌套调用和链式访问5.1 嵌套调用5…

产品用户手册难写在哪里?

产品手册不仅是一份产品使用说明书&#xff0c;更是企业通过互联网宣传和推销自己产品的一种普遍形式&#xff0c;对产品外观内容进行详细介绍对业务操作流程的详细讲解&#xff0c;通过产品手册对目标客户灌输产品意义和价值观。 生活中总会见到各式各样的产品手册&#xff0…

LaTeX使用graphicx+subfig实现子图合并+标题+子图标题

一、应用场景/需求 今天在LaTeX写论文的时候&#xff0c;发现自己需要使用几个图拼凑在一起&#xff0c;然后合到一张大图中去。也就是一张图包含若干张子图&#xff0c;然后若干张子图的大小可以自己设置&#xff0c;子图下面有子标题&#xff0c;而总的大图也有一个标题。例如…

PythonWeb开发基础(三)类Flask框架请求封装

课程地址&#xff1a;Python 工程师进阶技术图谱 文章目录类Flask框架请求封装HTTP请求解析的python实现1、解析查询字符串2、多值问题使用webob库解析请求Bug记录bug&#xff1a;AttributeError: module cgi has no attribute parse_qs类Flask框架请求封装 Web服务器 本质是…