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.rhkb.cn/news/456326.html

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

相关文章

【记录】VSCode|自用设置项

文章目录 1 基础配置1.1 自动保存1.2 编辑区自动换行1.3 选项卡换行1.4 空格代替制表符1.5 开启滚轮缩放 2 进阶设置2.1 选项卡不自我覆盖2.2 选项卡限制宽度2.3 选项卡组限制高度2.4 字体设置2.5 字体加粗2.6 侧边栏2.7 沉浸式代码模式 Zen Mode2.8 设置 Zen 模式的选项卡组 3…

家用wifi的ip地址固定吗?换wifi就是换ip地址吗

在探讨家用WiFi的IP地址是否固定&#xff0c;以及换WiFi是否就意味着换IP地址这两个问题时&#xff0c;我们首先需要明确几个关键概念&#xff1a;IP地址、家用WiFi网络、以及它们之间的相互作用。 一、家用WiFi的IP地址固定性 家用WiFi环境中的IP地址通常涉及两类&#xff1a…

文档透明加密系统怎么用?五款透明加密软件汇总!2024热门推荐,实测分享!

数据泄露事件频发&#xff0c;让无数企业谈之色变。 想要自动对存储在计算机上的文档进行加密吗&#xff1f; 怎么在不影响日常工作的前提&#xff0c;确保文档在存储和传输过程中的安全&#xff1f; 透明加密系统来助力&#xff01; 本文&#xff0c;将详细介绍文档透明加密…

解决vue使用pdfdist-mergeofd插件时报错polyfills

pdfdist-mergeofd 该插件主要是为了解决pdf-js和ofd-js共同使用时产生的依赖冲突问题&#xff0c;具体可看这位博主的文章同时使用ofdjs和pdfjs遇到的问题&#xff0c;和解决方法——懒加载 首先看下报错信息 ERROR in ./node_modules/.pnpm/pdfdist-mergeofd2.2.228_webpa…

人工智能算法之双倍体遗传算法(DGA)

人工智能算法之双倍体遗传算法&#xff08;DGA&#xff09; 双倍体遗传算法是一种改进的遗传算法&#xff0c;借鉴了生物中双倍体&#xff08;每个体细胞中具有两套染色体&#xff09;的遗传机制。传统遗传算法中的个体通常是单倍体&#xff08;单套基因&#xff09;&#xff0…

使用 v-html 指令渲染的标签, 标签内绑定的 click 事件不生效

背景 在项目开发中&#xff0c;实现用户友好的输入交互是提升用户体验的关键之一。例如&#xff0c;在客服对话框中&#xff0c;其中有包含多个快捷选项用于快速问答&#xff0c;每个快捷选项都是一个可点击的按钮&#xff0c;并需要绑定点击事件来执行相应操作。然而&#xf…

数据类型【MySQL】

文章目录 建立表查看表删除表数据类型floatcharvarcharchar&&varchar 时间日期类型enum和setenum和set查找 建立表 mysql> create table if not exists user1(-> id int ,-> name varchar (20) comment 用户名 ,-> password char (32) comment 用户名的…

软考(中级-软件设计师)算法分析篇(1024)

三、算法设计与分析 #1024程序员节|正文# 一、分治法 1.1 分而治之 对于一个规模为n的问题&#xff0c;若该问题可以容易的解决&#xff08;比如说规模较小&#xff0c;则直接解决&#xff0c;否则将其分解为k个规模较小的问题&#xff0c;这些子问题相互独立且与原问题形…

数组类型应用举例

在main.cpp里输入程序如下&#xff1a; #include "stdio.h" //使能printf()函数 #include <stdlib.h> //使能exit(); #define My_array_Size 10 //定义用My_array_Size代替 unsigned char My_array[My_array_Size]; //声明数组My_arra…

集群分发脚本

我的后端学习大纲 我的Linux环境搭建学习大纲 8.2.scp安全拷贝: 1.命令格式&#xff1a;scp -r $pdir/$fname $user$host:$pdir/$fname2.具体命令&#xff1a; scp -r jdk1.8.0_321/ rootHadoop104:/opt/module 3.实际操作&#xff1a; 3.1.在hadoop2和hadoop3&#xff0c;had…

Verilog 0x01 基础

硬件描述语言 0x00 数电逻辑符号 与 & 或 | 异或 ^ 同或 ~^0x01 基本结构 1.1 线网&#xff08;wire&#xff09; wire 类型表示硬件单元之间的物理连线&#xff0c;由其连接的器件输出端连续驱动 如果没有驱动元件连接到 wire 型变量&#xff0c;缺省值一般为 “Z” …

h5页面与小程序页面互相跳转

小程序跳转h5页面 一个home页 /pages/home/home 一个含有点击事件的元素&#xff1a;<button type"primary" bind:tap"toWebView">点击跳转h5页面</button>toWebView(){ wx.navigateTo({ url: /pages/webview/webview }) } 一个webView页 /pa…

数据结构——队列和栈

目录 一、栈 1、概念与结构 2、栈的结构与初始化 3、入栈 4、出栈 5、取栈顶元素 6、取栈中有效元素个数 7、栈是否为空 二、队列 1、概念与结构 2、队列的结构与初始化 3、入队列 4、出队列 5、取队头数据 6、取队尾数据 7、队列判空 8、队列中有效元素个数 练习题目链 一…

(一)Mysql篇---Mysql整体架构

MySql框架浅析 首先&#xff0c;上一张图先让各位看看大致结构&#xff1a; 从上到下&#xff0c;依次说一下结构&#xff1a; 连接层&#xff1a;这里主要是处理客户端和数据库连接的&#xff0c;直接使用的Tomcat的连接池&#xff0c;可以调整最大连接数&#xff1b; 服务…

精益思维在新能源汽车研发中的应用体现

近年来&#xff0c;新能源汽车作为绿色出行的重要载体&#xff0c;其研发与生产模式正经历着深刻的变革。精益思维&#xff0c;这一源自制造业的管理理念&#xff0c;正逐步渗透并深刻影响着新能源汽车的研发过程&#xff0c;不仅提升了产品质量与生产效率&#xff0c;还促进了…

汽车级DC-DC转换器英飞凌TLF35584

上汽荣威都在用的汽车级DC-DC转换器英飞凌TLF35584 今天平台君从IPBrain数据库中给大家带来的一款由Infineon(英飞凌)推出的一款多路输出安全电源芯片,具备高可靠性和安全性。适用于汽车电子系统中的多种应用场景,如车身控制、安全气囊、防抱死制动系统,电子稳定控制系统等。…

数据结构:堆的应用

堆排序 假定有一组数据极多的数&#xff0c;让我们进行排序&#xff0c;那我们很容易想到一种经典的排序方法&#xff0c;冒泡排序&#xff0c;我们对冒泡排序的时间复杂度进行分析&#xff1a; 显然&#xff0c;冒泡排序的时间复杂度是O&#xff08;n^2&#xff09;,当数据量…

软考(中级-软件设计师)计算机系统篇(1024)

#1024程序员节|正文# 六、树和二叉树 6.1 树的基本概念 描述结果结点的度子结点的个数树的度最大结点的度叶子结点没有子结点的结点内部结点除根结点和叶子结点外的结点父节点有子结点的结点子节点有父结点的结点兄弟节点有同一个父结点的结点层次4层 6.2 二叉树的基本概念…

【Javaee】网络原理—TCP协议的核心机制

前言 TCP/IP五层协议是互联网中的主流模型&#xff0c;为网络通信提供了一个稳固的框架。 主要包含了应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;物理层。 本篇主要介绍传输层的TCP协议的核心机制 一. 确认应答&#xff08;ack&#xf…

线程本地变量-ThreadLocal

一、ThreadLocal简介 ThreadLocal叫做线程变量&#xff0c;意思是ThreadLocal中填充的变量属于当前线程&#xff0c;该变量对其他线程而言是隔离的&#xff0c;也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本&#xff0c;那么每个线程可…