C语言_通讯录_进阶

引言:在之前的项目中,我们所用的通讯录是静态版本,也就是常规的固定数组大小,但仔细思考,在现实的复杂环境中,是很难做到这样死板,所以在学习过动态内存的章节后,我们将通讯录重新修改,在不断添加联系人的环节中,我们也不断通过realloc的扩容动态空间。

修改的地方:

  1. 在之前的静态版本中,我们只需要记录当前存储的通讯录个数即可,那么我们现在即将要改进到动态版本,将通讯录数组改变为指向一块空间,我们还需要记录通讯录的容量,意思就是当然存储个数 == 通讯容量的时候对通讯录动态开辟的空间进行重新扩容,以及对通讯容量进行增加

  2. 在添加联系人环节中,我们不在需要判断有没有装满通讯录,而是判断通讯录有没有达到扩容的条件。

  3. 在我们退出项目的时候,需要对动态开辟的空间通进行释放,将指针置为NULL,将容量以及存储个数置为0。

  4. 在模拟快排的函数中,我们可以把元素个数改变为当前存储的通讯录个数。

以上就是静态通讯录转变到动态通讯录的大致改变方向,接下来就是我们需要实践的地方。

Contact.h

#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>
#include <assert.h>
#include <stdlib.h>#define MAX 20
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#define DEFAULT_SZ 1
#define INT_SZ 2enum OPTION
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT
};typedef struct People_Info People_Info;
struct People_Info
{char name[MAX_NAME];int age;char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];
};//动态版本
typedef struct Contact Contact;
struct Contact
{People_Info* data;//指向存放数据的空间int sz;//记录当前存储个数int capacity;//记录最大可存储容量
};//初始化通讯录
void InitContact(Contact* Con);//添加联系人
void AddContact(Contact* Con);//显示全部联系人
void ShowContact(const Contact* Con);//删除指定联系人
void DelContact(Contact* Con);//查找指定联系人
void SearchContact(const Contact* Con);//修改指定联系人信息
void ModifyContact(Contact* Con);//字符串比较函数
int my_strcmp(char* str1, char* str2);//手搓快排
void Bubble_sort(People_Info* stu, int num, int sz, int (*cmp_by_name)(void* pf1, void* pf2));//声明cmp_by_name -> 模拟快排所需要的函数
int cmp_by_name(void* pf1, void* pf2);//销毁动态开辟的空间
void DestroyContact(Contact* Con);

Contact.c

动态通讯录进行初始化

void InitContact(Contact* Con)
{assert(Con != NULL);People_Info* pc = (People_Info*)malloc(DEFAULT_SZ * sizeof(People_Info));if (pc == NULL){perror("InitContact:");return;}Con->data = pc;Con->sz = 0;Con->capacity = DEFAULT_SZ;
}

添加联系人

//检查容量
int CheckCapacity(Contact* Con)
{if (Con->sz == Con->capacity){People_Info* ptr = (People_Info*)realloc(Con->data, (Con->capacity + INT_SZ) * sizeof(People_Info));if (ptr == NULL){perror("CheckCapacity:");return 0;}else{Con->data = ptr;Con->capacity += INT_SZ;printf("增容成功!!!\n");return 1;}}return 1;
}//添加联系人
void AddContact(Contact* Con)
{assert(Con != NULL);if (0 == CheckCapacity(Con)){printf("增容失败,请检查!!!\n");return;}printf("请输入你的名字:");scanf("%s", Con->data[Con->sz].name);Clear();printf("请输入你的年龄:");scanf("%d", &(Con->data[Con->sz].age));printf("请输入你的性别:");scanf("%s", Con->data[Con->sz].sex);Clear();printf("请输入你的电话:");scanf("%s", Con->data[Con->sz].tele);Clear();printf("请输入你的地址:");scanf("%s", Con->data[Con->sz].addr);Clear();printf("添加成功!!!\n");Con->sz++;
}

显示全部联系人

// 显示全部联系人
void ShowContact(const Contact* Con)
{assert(Con != NULL);title();if (Con->sz == 0){printf("暂无联系人!!!\n");return;}int i = 0;for (i = 0; i < Con->sz; i++){printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",Con->data[i].name,Con->data[i].age,Con->data[i].sex,Con->data[i].tele,Con->data[i].addr);}
}

删除指定联系人

//字符串比较
int my_strcmp(char* str1, char* str2)
{while (*str1 == *str2){if (*str1 == '\0'){return 0;}str1++;str2++;}if (*str1 > *str2){return 1;}else{return -1;}
}//找动态空间中是否存在对应的名字
int Find_Name(Contact* Con, char* name)
{int i = 0;for (i = 0; i < Con->sz; i++){if (my_strcmp(Con->data[i].name, name) == 0){return i;}}return -1;
}//删除指定联系人
void DelContact(Contact* Con)
{assert(Con != NULL);if (Con->sz == 0){printf("暂无联系人!!!\n");return;}char name[MAX_NAME] = { 0 };printf("请输入需要删除的名字:");scanf("%s", name);int pos = Find_Name(Con, name);if (pos == -1){printf("没有找到指定删除的联系人名字!!!\n");return;}int i = 0;for (i = pos; i < Con->sz - 1; i++){Con->data[i] = Con->data[i + 1];}printf("删除成功!!!\n");Con->sz--;
}

查找指定联系人

//字符串比较
int my_strcmp(char* str1, char* str2)
{while (*str1 == *str2){if (*str1 == '\0'){return 0;}str1++;str2++;}if (*str1 > *str2){return 1;}else{return -1;}
}//找动态空间中是否存在对应的名字
int Find_Name(Contact* Con, char* name)
{int i = 0;for (i = 0; i < Con->sz; i++){if (my_strcmp(Con->data[i].name, name) == 0){return i;}}return -1;
}//查找指定联系人
void SearchContact(const Contact* Con)
{assert(Con != NULL);if (Con->sz == 0){printf("暂无添加联系人!!!\n");return;}char name[MAX_NAME] = { 0 };printf("请输人查找指定联系人的名字:");scanf("%s", name);int pos = Find_Name(Con, name);if (pos == -1){printf("暂无查找到指定联系人!!!\n");return;}else{title();printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",Con->data[pos].name,Con->data[pos].age,Con->data[pos].sex,Con->data[pos].tele,Con->data[pos].addr);}
}

修改指定联系人信息

//字符串比较
int my_strcmp(char* str1, char* str2)
{while (*str1 == *str2){if (*str1 == '\0'){return 0;}str1++;str2++;}if (*str1 > *str2){return 1;}else{return -1;}
}//找动态空间中是否存在对应的名字
int Find_Name(Contact* Con, char* name)
{int i = 0;for (i = 0; i < Con->sz; i++){if (my_strcmp(Con->data[i].name, name) == 0){return i;}}return -1;
}//修改指定联系人信息 - 菜单
void menu_modify()
{printf("*****************************\n");printf("***** 1.Name     2.Age  *****\n");printf("***** 3.Sex      4.Tele *****\n");printf("***** 5.Addr     0.Exit *****\n");printf("*****************************\n");
}//修改指定联系人信息
void ModifyContact(Contact* Con)
{assert(Con != NULL);if (Con->sz == 0){printf("暂无添加联系人信息\n");return;}char name[MAX_NAME] = { 0 };printf("请输入联系人名字:");scanf("%s", name);int pos = Find_Name(Con, name);if (pos == -1){printf("没有找到指定联系人!!!\n");return;}else{int input = 0;do{menu_modify();printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("请输入你的名字:");scanf("%s", Con->data[pos].name);break;case 2:printf("请输入你的年龄:");scanf("%d", &(Con->data[pos].age));break;case 3:printf("请输入你的性别:");scanf("%s", Con->data[pos].sex);break;case 4:printf("请输入你的电话:");scanf("%s", Con->data[pos].tele);break;case 5:printf("请输入你的地址:");scanf("%s", Con->data[pos].addr);break;case 0:printf("退出选项!!!\n");break;default:printf("输入有误,请重新选择!!!\n");break;}} while (input);}
}

模拟快排并排序动态空间中的通讯录信息

int cmp_by_name(void* pf1, void* pf2)
{return my_strcmp(((People_Info*)pf1)->name, ((People_Info*)pf2)->name);
}void Swap(char* buf1, char* buf2, int sz)
{int i = 0;for (i = 0; i < sz; i++){char tmp = *(buf1 + i);*(buf1 + i) = *(buf2 + i);*(buf2 + i) = tmp;}
}void Bubble_sort(void* stu, int num, int sz, int (*cmp_by_name)(void* pf1, void* pf2))
{int i = 0;for (i = 0; i < num; i++){int j = 0;for (j = 0; j < num - i - 1; j++){if (cmp_by_name((char*)stu + j * sz, (char*)stu + (j + 1) * sz) < 0){Swap((char*)stu + j * sz, (char*)stu + (j + 1) * sz, sz);}}}
}

:这部分也是我个人认为比较难的一块,本身的模拟快排难度就不小了再加上排序通讯录信息,真的让人爆炸。

销毁动态空间

//销毁动态开辟的空间
void DestroyContact(Contact* Con)
{free(Con->data);Con->data = NULL;Con->capacity = 0;Con->sz = 0;
}

test.c

通讯录项目逻辑

#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("******************************\n");
}void test()
{int input = 0;Contact Con;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:Bubble_sort(&(Con.data[0]), Con.sz, sizeof(People_Info), cmp_by_name);break;case EXIT:DestroyContact(&Con);break;default:printf("输入有误,请重新输入!!!\n");break;}} while (input);
}int main()
{test();return 0;
}

总结:以上代码中,能模拟实现的库函数我都尽量手搓了,在写项目的同时也不要忘记巩固之前所学的内容。本项目还是在于增删查改的操作,逻辑上并不难以理解,但是操作上还需要我们结合自身前面所学的基础,只有基础打牢以及扎实,才能在这个项目中显得游刃有余。

本章完~

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

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

相关文章

Spring Cache Caffeine 高性能缓存库

​ Caffeine 背景 Caffeine是一个高性能的Java缓存库&#xff0c;它基于Guava Cache进行了增强&#xff0c;提供了更加出色的缓存体验。Caffeine的主要特点包括&#xff1a; 高性能&#xff1a;Caffeine使用了Java 8最新的StampedLock乐观锁技术&#xff0c;极大地提高了缓存…

三国杀钓鱼自动化

三国杀钓鱼脚本 前言 本来是想做必杀的&#xff0c;但是后来测试了大约400钓发现纯靠连点没有漏掉的鱼&#xff0c;所以必杀功能就舍弃了。 我pyinstaller打包后运行.exe居然黑屏了&#xff1f;&#xff1f;&#xff1f;可能是多进程报错处理没写好&#xff0c;反正还是用vsc…

笔试第五行

static作用&#xff1a; 1.函数体内&#xff0c;一个被声明为静态的变量在这一函数被调用时值维持不变。 2.函数体外&#xff0c;模块内&#xff0c;一个被声明为静态的变量可以被模块内函数访问&#xff0c;但不能模块外函数访问&#xff0c;这是一个本地的全局变量。 3.模…

k8s部署使用有状态服务statefulset部署eureka集群,需登录认证

一、构建eureka集群镜像 1、编写dockerfile文件&#xff0c;此处基础镜像为arm版本&#xff0c;eureka目录中文件内容&#xff1a;application-dev.yml、Dockerfile、eureka-server-1.0-SNAPSHOT.jar(添加登录认证模块&#xff0c;文章最后附上下载连接) FROM mdsol/java8-j…

Go使用exec.Command() 执行脚本时出现:file or directory not found

使用 Go 提供的 exec.Command() 执行脚本时出现了未找到脚本的 bug&#xff0c;三个排查思路 &#xff1a; exec.Command(execName, args…) 脚本名字不允许相对路径 exec.Command(execName, args…) execName 只能有脚本名&#xff0c;不允许出现参数 如果你是使用 Windows …

为什么要使用网络IO内存数据库?

1.摘要 学习Redis的时候&#xff0c;我有个疑问&#xff1a;Redis缓存是内存数据库&#xff0c;但是它部署在独立的一个服务器上&#xff0c;那么应用服务器访问redis不是要通过网络吗&#xff0c;那么是不是还不如从本地服务器读取数据库的效率 &#xff1f;结论是&#xff1a…

Ubuntu github 网速慢 打不开

1.在ipaddress 网站查找一下github的dns 并复制到/etc/hosts https://www.ipaddress.com/website/github.com/ 140.82.113.4 github.com 185.199.108.133 raw.githubusercontent.com #185.199.109.133 raw.githubusercontent.com #185.199.110.133 raw.githubusercontent.com …

[图像处理] 基于CleanVision库清洗图像数据集

CleanVision是一个开源的Python库&#xff0c;旨在帮助用户自动检测图像数据集中可能影响机器学习项目的常见问题。该库被设计为计算机视觉项目的初步工具&#xff0c;以便在应用机器学习之前发现并解决数据集中的问题。CleanVision的核心功能包括检测完全重复、近似重复、模糊…

ML 系列:机器学习和深度学习的深层次总结(17)从样本空间到概率规则概率

一、说明 概率是支撑大部分统计分析的基本概念。从本质上讲&#xff0c;概率提供了一个框架&#xff0c;用于量化不确定性并对未来事件做出明智的预测。无论您是在掷骰子、预测天气还是评估金融市场的风险&#xff0c;概率都是帮助您驾驭不确定性的工具。本篇将讲授概率的原理和…

论文阅读:Guided Linear Upsampling

今天介绍一篇有趣的文章&#xff0c;Guided Linear Upsampling&#xff0c;基于引导的线性上采样&#xff0c;这是发表在 ACM transaction on Graphic 的一篇工作。 Abstract 引导上采样是加速高分辨率图像处理的一种有效方法。在本文中&#xff0c;文章作者提出了一种简单而…

博客搭建之路:hexo搜索引擎收录

文章目录 hexo搜索引擎收录以百度为例 hexo搜索引擎收录 hexo版本5.0.2 npm版本6.14.7 next版本7.8.0 写博客的目的肯定不是就只有自己能看到&#xff0c;想让更多的人看到就需要可以让搜索引擎来收录对应的文章。hexo支持生成站点地图sitemap 在hexo下的_config.yml中配置站点…

问:MySQL表过大,你有哪些优化实践?

当MySQL单表记录数过大时&#xff0c;数据库的CRUD&#xff08;创建、读取、更新、删除&#xff09;性能会明显下降。为了提升性能&#xff0c;我们需要采取一些优化措施。本文将详细介绍几种常见的优化方案。 1. 限定数据的范围 描述 务必禁止不带任何限制数据范围条件的查…

优先算法——移动零(双指针)

目录 1. 题目解析 2. 算法原理 3.代码实现 题目: 力扣题目链接&#xff1a;移动零 1. 题目解析 题目截图如下&#xff1a; 不过要注意&#xff0c;这个移动题目要求是在原数组中原地操作&#xff0c;不能新额外开辟一个数组来修改。 2. 算法原理 这个原理可以称之为数…

node和npm

背景&#xff08;js&#xff09; 1、为什么js能操作DOM和BOM? 原因&#xff1a;每个浏览器都内置了DOM、BOM这样的API函数 2、浏览器中的js运行环境&#xff1f; v8引擎&#xff1a;负责解析和执行js代码 内置API&#xff1a;由运行环境提供的特殊接口&#xff0c;只能在所…

Python | Leetcode Python题解之第507题完美数

题目&#xff1a; 题解&#xff1a; class Solution:def checkPerfectNumber(self, num: int) -> bool:if num 1:return Falsesum 1d 2while d * d < num:if num % d 0:sum dif d * d < num:sum num / dd 1return sum num

使用预训练的BERT进行金融领域问答

获取更多完整项目代码数据集&#xff0c;点此加入免费社区群 &#xff1a; 首页-置顶必看 1. 项目简介 本项目旨在开发并优化一个基于预训练BERT模型的问答系统&#xff0c;专注于金融领域的应用。随着金融市场信息复杂性和规模的增加&#xff0c;传统的信息检索方法难以高效…

Python 爬虫项目实战:爬取某云热歌榜歌曲

一、网络爬虫的定义 网络爬虫&#xff08;Web Crawler&#xff09;&#xff0c;也成为网页蜘蛛或者网页机器人&#xff0c;是一种按照既定规则自动浏览网络并提取信息的程序。爬虫的主要用途包括数据采集、网络索以及内容抓取等。 二、爬虫基本原理 1、种子URL&#xff1a;爬…

01 springboot-整合日志(logback-config.xml)

logback-config.xml 是一个用于配置 Logback 日志框架的 XML 文件&#xff0c;通常位于项目的 classpath 下的根目录或者 src/main/resources 目录下。 Logback 提供了丰富的配置选项&#xff0c;可以满足各种不同的日志需求。需要根据具体情况进行配置。 项目创建&#xff0…

学习规划网络安全工程师之路

要成为一名网络安全工程师&#xff0c;尤其是在物联网安全日渐重要的背景下&#xff0c;你需要制定一个系统的学习规划&#xff0c;以掌握相关知识和技能。以下是一个具体的学习规划&#xff0c;分为基础阶段、进阶阶段和实践阶段。 学习规划 一、基础阶段&#xff08;1-3个月…

CCF-BDCI大数据与计算智能大赛TOP4-京东生鲜

2023 CCF 大数据与计算智能大赛《线上线下全场景生鲜超市库存履约一体化决策》top4南山论剑 摘要1 数据预处理1.1 数据整合1.2 数据划分 2 特征工程2.1 静态特征2.2 动态特征 3 方案设计3.1 数据构造3.2 模型训练3.3 模型融合3.4库存分配3.5 方案对比 链接: CCFBDCI-线上线下全…