c语言小课设--通讯录(动态内存管理)

前言:

在没学动态内存管理之前,我们用的结构体,数组等都是静态分配内存的,也就是说数组的长度是固定的,但是这并不满足我们的实际需求,所以在通讯录项目里面我就用到了动态内存分布。简单来说,就是当需要储存的联系人数据太多了的时候,我们就可以扩大一点空间用来存放新的数据,也就是说实现了要多少,就开辟多少的空间。

项目介绍:

该项目实现一个通讯录功能,除了能根据具体需求扩大空间之外,也实现了最基本基本的增删查改等功能,并在退出通讯录时销毁创造的空间,从而不造成内存泄露。

另外,这个项目由三部分组成,函数功能的实现在Contact.c源文件中,各种头文件、函数等声明则由文件Contact.h来实现,最后测试在源文件test.c文件中进行。

一、teat.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"enum Option {Exit,add,modify,del,search,show,sort
};void menu() {printf("************************\n");printf("**1.添加    2.修改******\n");printf("**3.删除    4.搜索******\n");printf("**5.展示    6.排序******\n");printf("**0.退出          ******\n");printf("************************\n");
}int main() {int input = 0;Contacts Con;Init(&Con);do {menu();printf("请输入你的选择--》\n");scanf("%d", &input);switch (input) {case add://添加Add_Peo(&Con);break;case modify://修改Modify_Peo(&Con);break;case del:Del_Peo(&Con);break;case search:Sear_Peo(&Con); break;case show:Show_Peo(&Con);break;case sort:Sort_Peo(&Con);break;case Exit:Destory_Contacts(&Con);printf("退出通讯录\n");break;default:printf("你的输入有误!\n");break;}} while (input != 0);return 0;
}

二、Contact.h头文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>#define name_max 20
#define sex_max 5
#define tele_max 12
#define addr_max 20
#define num_max 100
#define default_cap 3typedef struct PeoInfo {char name[name_max];char sex[sex_max];char tele[tele_max];int age;
}PeoInfo;
//静态通讯录版本
//typedef struct Contacts {
//	PeoInfo data[num_max];
//	int sz;
//}Contacts;
//动态版本
typedef struct Contacts {PeoInfo *data;//存放数据int sz;//记录当前联系人的数量int cap;//当前通讯录的容量
}Contacts;//初始化通讯录
void Init(Contacts* Con);
//添加功能
void Add_Peo(Contacts* Con);
//修改功能
void Modify_Peo(Contacts* Con);
//删除联系人
void Del_Peo(Contacts* Con);
//展示联系人
void Show_Peo(Contacts* Con);
//查询联系人
void Sear_Peo(Contacts* Con);
//排序
void Sort_Peo(Contacts* Con);

三、Contact.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"// 自定义比较剂,按名字字典序排序int cmp(void* e1,void *e2) {//printf("%s %s\n", (, ((struct PeoInfo*)e2)->name);return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}//初始化通讯录
void Init(Contacts* Con) {assert(Con);Con->sz = 0;Con->cap = default_cap;Con->data = calloc(Con->cap, sizeof(PeoInfo));if (Con->data == NULL) {printf("初始化失败\n");return;}
}//void Init(Contacts* Con) {
//	assert(Con);
//	Con->sz = 0;
//	memset(Con->data, 0, sizeof(Con->data));
//}//增加容量
void check_cap(Contacts* Con) {PeoInfo* ptr = realloc(Con->data, (Con->cap + 2) * sizeof(PeoInfo));if (ptr != NULL) {Con->data = ptr;Con->cap += 2;printf("增容成功\n");}else {perror("AddContacts->realloc");return;}}
//添加功能
//动态版本
void Add_Peo(Contacts* Con) {assert(Con);if (Con->sz == Con->cap) {check_cap(Con);}printf("请输入添加人的姓名\n");scanf("%s", Con->data[Con->sz].name);printf("请输入添加人的年龄\n");scanf("%d", &Con->data[Con->sz].age);printf("请输入添加人的性别\n");scanf("%s", Con->data[Con->sz].sex);printf("请输入添加人的号码\n");scanf("%s", Con->data[Con->sz].tele);Con->sz++;return;
}
//静态版本
//void Add_Peo(Contacts* Con) {
//	assert(Con);
//	if (Con->sz == num_max) {
//		printf("通讯录已满\n");
//		return;
//	}
//	else {
//		printf("请输入添加人的姓名\n");
//		scanf("%s", Con->data[Con->sz].name);
//		printf("请输入添加人的年龄\n");
//		scanf("%d", &Con->data[Con->sz].age);
//		printf("请输入添加人的性别\n");
//		scanf("%s", Con->data[Con->sz].sex);
//		printf("请输入添加人的号码\n");
//		scanf("%s", Con->data[Con->sz].tele);
//		Con->sz++;
//		return;
//	}
//}
//按名字查找
int find_name(Contacts* Con,char *tager) {assert(Con);for (int i = 0; i < Con->sz; i++) {if (strcmp(Con->data[i].name, tager)==0) {return i;}}return -1;}
//修改功能
void Modify_Peo(Contacts* Con) {assert(Con);char name[name_max] = {0};while (1) {printf("请输入你要修改联系人的名字\n");scanf("%s", name);int k = find_name(Con, name);if ( k!= -1&&k>=0&&k<Con->sz) {printf("请重新输入修改的姓名\n");scanf("%s", Con->data[k].name);printf("请重新输入修改的的年龄\n");scanf("%d",&Con->data[k].age);printf("请重新输入修改的的性别\n");scanf("%s", Con->data[k].sex);printf("请重新输入修改的的号码\n");scanf("%s", Con->data[k].tele);printf("修改成功!\n");break;}else {printf("查无此人\n");break;}}}
//删除联系人
void Del_Peo(Contacts* Con) {assert(Con);if (Con->sz == 0) {printf("该通讯录还没有联系人\n");return;}printf("请输入你要删除联系人的姓名\n");char name1[name_max] = { 0 };scanf("%s", name1);int k = find_name(Con, name1);if (k != -1&&k>=0&&k<Con->sz) {for (int i = k; i < Con->sz - 1; i++) {Con->data[i] = Con->data[i + 1];}Con->sz--;printf("删除成功\n");}else {printf("查无此人\n");return;}
}
//展示联系人
void Show_Peo(Contacts* Con) {assert(Con);if (Con->sz == 0) {printf("没有联系人\n");return;}printf("-------------------------------------------------\n");printf("|%-20s |%-5s |%-5s |%-12s| \n","姓名","年龄","性别","号码");printf("-------------------------------------------------\n");for (int i = 0; i < Con->sz; i++) {printf("|%-20s |%-5d |%-5s |%-12s|\n", Con->data[i].name, Con->data[i].age, Con->data[i].sex, Con->data[i].tele);if (i != (Con->sz - 1)) {printf("-------------------------------------------------\n");}}printf("-------------------------------------------------\n");
}
//查询联系人
void Sear_Peo(Contacts* Con) {assert(Con);char tager[name_max] = { 0 };if (Con->sz == 0) {printf("没有联系人\n");return;}printf("请输入你要查找的名字\n");scanf("%s", tager);int k = find_name(Con, tager);if (k != -1 && k >= 0 && k < Con->sz) {printf("-------------------------------------------------\n");printf("|%-20s |%-5s |%-5s |%-12s| \n", "姓名", "年龄", "性别", "号码");printf("|%-20s |%-5d |%-5s |%-12s|\n", Con->data[k].name, Con->data[k].age, Con->data[k].sex, Con->data[k].tele);printf("-------------------------------------------------\n");}else {printf("查无此人\n");return;}
}
//排序
void Sort_Peo(Contacts* Con) {assert(Con);qsort(Con->data, Con->sz, sizeof(struct PeoInfo), cmp);printf("排序成功\n");return;
}
//销毁通讯录
void Destory_Contacts(Contacts* Con) {free(Con->data);Con->data = NULL;Con->cap = 0;Con->sz = 0;
}

好了以上就是整个项目的源代码了,是不是很简单呢?感兴趣的可以自己去试试哦!

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

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

相关文章

docker 基本操作

目录 一、docker 概述 二、容器 2.1容器的特性 2.2namespace的六项隔离 三、docker与虚拟机的区别 四、Docker核心概念 五、docker 基本操作命令 镜像操作 1、搜索镜像 2、获取镜像 3、查看镜像信息 ​编辑 4、查看下载的镜像文件信息 5、查看下载到本地的所有镜…

搭建智能桥梁,Amazon CodeWhisperer助您轻松编程

零&#xff1a;前言 随着时间的推移&#xff0c;人工智能技术以惊人的速度向前发展&#xff0c;正掀起着全新的编程范式革命。不仅仅局限于代码生成&#xff0c;智能编程助手等创新应用也进一步提升了开发效率和代码质量&#xff0c;极大地推动着软件开发领域的快速繁荣。 当前…

SpringCloud(一)Eureka、Nacos、Feign、Gateway

文章目录 概述微服务技术对比 Eureka服务远程调用服务提供者和消费者Eureka注册中心搭建注册中心服务注册服务发现Ribbon负载均衡负载均衡策略饥饿加载 NacosNacos与Eureka对比Nacos服务注册Nacos服务分集群存储NacosRule负载均衡服务实例权重设置环境隔离 Nacos配置管理配置热…

用于自然语言处理的 Python:理解文本数据

一、说明 Python是一种功能强大的编程语言&#xff0c;在自然语言处理&#xff08;NLP&#xff09;领域获得了极大的普及。凭借其丰富的库集&#xff0c;Python 为处理和分析文本数据提供了一个全面的生态系统。在本文中&#xff0c;我们将介绍 Python for NLP 的一些基础知识&…

2023 彩虹全新 SUP 模板,卡卡云模板修复版

2023 彩虹全新 SUP 模板&#xff0c;卡卡云模板&#xff0c;首页美化&#xff0c;登陆页美化&#xff0c;修复了 PC 端购物车页面显示不正常的问题。 使用教程 将这俩个数据库文件导入数据库&#xff1b; 其他的直接导入网站根目录覆盖就好&#xff1b; 若首页显示不正常&a…

计算机网络学习易错点(持续更新~~~)

目录 概述 1.internet和Internet的区别 2.面向连接和无连接 3.不同的T 4.传输速率和传播速率 5.传播时延和传输时延&#xff08;发送时延&#xff09; 6.语法&#xff0c;语义和同步 一.物理层 1.传输媒体与物理层 2.同步通信和异步通信 3.位同步&#xff08;比特同…

nginx多文件组织

背景&#xff1a; nginx的话&#xff0c;有时候&#xff0c;想部署多个配置&#xff0c;比如&#xff1a;使用不同的端口配置不同的web工程。 比如&#xff1a;8081部署&#xff1a;项目1的web页面。 8082部署&#xff1a;项目2的web页面。 1)nginx.conf worker_processes…

Google vs IBM vs Microsoft: 哪个在线数据分析师证书最好

Google vs IBM vs Microsoft: 哪个在线数据分析师证书最好&#xff1f; 对目前市场上前三个数据分析师证书进行审查和比较|Madison Hunter 似乎每个重要的公司都推出了自己版本的同一事物&#xff1a;专业数据分析师认证&#xff0c;旨在使您成为雇主的下一个热门商品。 随着…

7.JavaScript-vue

1 JavaScript html完成了架子&#xff0c;css做了美化&#xff0c;但是网页是死的&#xff0c;我们需要给他注入灵魂&#xff0c;所以接下来我们需要学习JavaScript&#xff0c;这门语言会让我们的页面能够和用户进行交互。 1.1 介绍 通过代码/js效果演示提供资料进行效果演…

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石⑤

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石⑤ 第十九章 驱动程序基石⑤19.9 mmap19.9.1 内存映射现象与数据结构19.9.2 ARM架构内存映射简介19.9.2.1 一级页表映射过程19.9.2.2 二级页表映射过程 19.9.3 怎么给APP新建一块内存映射19.9.3.1 mmap调用过程19.9.3.2 cach…

华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos

华为云云耀云服务器L实例评测&#xff5c;部署在线轻量级备忘录 memos 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 产品优势1.3 应用场景1.4 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 memos3.1 memos介绍3.2 Docker 环境搭建…

C语言数组

C 语言支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量&#xff0c;比如 runoob0、runoob1、...、runoob99&#xff0c;而…

Scala第十章

Scala第十章 章节目标 1.数组 2.元组 3.列表 4.集 5.映射 6.迭代器 7.函数式编程 8.案例&#xff1a;学生成绩单 scala总目录 文档资料下载

Jmeter分布式压力测试

目录 1、场景 2、原理 3、注意事项 4、slave配置 5、master配置 6、脚本执行 1、场景 在做性能测试时&#xff0c;单台机器进行压测可能达不到预期结果。主要原因是单台机器压到一定程度会出现瓶颈。也有可能单机网卡跟不上造成结果偏差较大。 例如4C8G的window server机…

防火墙基础之H3C防火墙分支与分支之间双向地址转换

分支与分支之间双向地址转换 原理概述&#xff1a; 防火墙&#xff08;英语&#xff1a;Firewall&#xff09;技术是通过有机结合各类用于安全管理​与筛选的软件和硬件​设备&#xff0c;帮助计算机网络于其内、外网之间构建一道相对隔绝的保护屏障&#xff0c;以保护用户资…

029-从零搭建微服务-消息队列(一)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;mingyue: &#x1f389; 基于 Spring Boot、Spring Cloud & Alibaba 的分布式微服务架构基础服务中心 源…

ARP和DDOS攻击防御介绍

ARP攻击如何产生的&#xff1f; ARP如何进行有效的防御&#xff1f; ARP地址解析协议 已知对方ip地址&#xff0c;求得对方mac地址 交换机会自动学习&#xff1a; 当pc1想访问外网&#xff0c;会向外发一个广播包&#xff0c;交换机会收到一个广播包 ARP地址表&#xff1a; …

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石②

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石② 第十九章 驱动程序基石②19.3 异步通知19.3.1 适用场景19.3.2 使用流程19.3.3 驱动编程19.3.4 应用编程19.3.5 现场编程19.3.6 上机编程19.3.7 异步通知机制内核代码详解 19.4 阻塞与非阻塞19.4.1 应用编程19.4.2 驱动编程…

简历项目优化关键方法论-START

START方法论是非常著名的面试法则&#xff0c;经常被面试官使用的工具 Situation:情况、事情、项目需求是在什么情况下发生Task:任务&#xff0c;你负责的做的是什么Action:动作&#xff0c;针对这样的情况分析&#xff0c;你采用了什么行动方式Result:结果&#xff0c;在这样…

nodejs+vue流浪猫狗救助领养elementui

第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性&#xff1a;技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性&#xff1a; 11 3.3性能分析 11 3.4系统操作流程 12 3.4.1管理员登录流程 12 3.4.2信息添加流程 12 3.4.3信息删除流程 13 第四章 系统设计与…