当前位置: 首页 > news >正文

简易实现通讯录(1.0)

 前言

我们还是像以前一样,分为三个文件来书写,分别是contact.h,contact.c,test.c

分别用来声明函数,实现函数和测试函数功能,现在就让我们开始吧.

1.基本逻辑

首先我们定义通讯录里的数据,我们定义为结构体

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

然后我们希望这个通讯录有100条数据,我们也定义成一个结构体

typedef struct Contact
{PeoInfo data[100];int sz;//人的信息个数
}Contact;

接着就是经典设计一份菜单,然后switch case语句来选择要实现的功能

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");}

为了增强代码的可读性,我们将原来的case后面的数转换成了枚举常量.

enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT
};

接下来就是主函数部分,我们使用一个do while语句来保证循环可以一直进行

int main()
{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:SortContact(&con);break;case EXIT:break;default:printf("输入错误,请重新输入\n");}} while (input);return 0;
}

下面我们开始写函数.

为了方便修改通讯录中个人信息的大小,我们定义了一些宏来解决.

//类型的声明
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100

2.函数功能的实现

2.1初始化通讯录

void  InitContact(Contact* pc)
{assert(pc);pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}

2.2 添加功能

void AddContact(Contact* pc)
{assert(pc);if (pc->sz == MAX){printf("通讯录已满,无法增加");return;}printf("请输入名字:>\n");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>\n");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>\n");scanf("%s", (pc->data[pc->sz].sex));printf("请输入电话:>\n");scanf("%s", (pc->data[pc->sz].tele));printf("请输入地址:>\n");scanf("%s", (pc->data[pc->sz].addr));pc->sz++;printf("增加成功\n");
}

2.3 展示功能 

void ShowContact(const Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无需打印\n");return;}printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (int i = 0; i < pc->sz; i++){//打印信息printf("%-20s%-5d%-5s%-12s%-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}
}

2.4 查找函数

由于下面要实现的查找功能,修改删除功能都需要先找到该条数据,所以我们以姓名查找为例,定义一个查找函数.这样也能增强代码的复用性.

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;
}

2.5 删除联系人 

注:数组中的元素的删除不了的,只能覆盖,所以把后面的向前覆盖即可.

void DelContact(Contact* pc)
{char name[NAME_MAX];assert(pc);if (pc->sz == 0){printf("通讯录为空,无法删除\n");}printf("请输入要删除的人的名字\n");scanf("%s", name);//找到名字叫name的人int ret = FindByName(pc, name);//找到返回下标,找不到返回-1if (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");
}

2.6 查找联系人

void SearchContact(Contact* pc)
{assert(pc);char name[NAME_MAX];printf("请输入要查找的人的姓名\n");int ret = FindByName(pc->data, name);if (ret == -1){printf("要查找的人不存在\n");return;}printf("%-20s%-5d%-5s%-12s%-30s\n", pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}

2.7 修改联系人

void ModifyContact(Contact* pc)
{assert(pc);char name[NAME_MAX];scanf("%s", name);int ret = FindByName(pc, name);if (ret == -1){printf("要修改的人的信息不存在\n");return;}//修改的逻辑else{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");}}

2.8 按照姓名排序联系人

static int sort_by_name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}void SortContact(Contact* pc)
{if (pc->sz == 0){printf("一个人没有你排什么顺序,啊小丑!\n");}qsort(pc->data, pc->sz, sizeof((pc->data)[0]), sort_by_name);ShowContact(pc);
}

2.9 test.c

#define _CRT_SECURE_NO_WARNINGS#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");}
enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT
};int main()
{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:SortContact(&con);break;case EXIT:break;default:printf("输入错误,请重新输入\n");}} while (input);return 0;
}

2.10 contact.c

#define _CRT_SECURE_NO_WARNINGS #include "contact.h"void  InitContact(Contact* pc)
{assert(pc);pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}
void AddContact(Contact* pc)
{assert(pc);if (pc->sz == MAX){printf("通讯录已满,无法增加");return;}printf("请输入名字:>\n");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>\n");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>\n");scanf("%s", (pc->data[pc->sz].sex));printf("请输入电话:>\n");scanf("%s", (pc->data[pc->sz].tele));printf("请输入地址:>\n");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;}printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (int i = 0; i < pc->sz; i++){//打印信息printf("%-20s%-5d%-5s%-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");}printf("请输入要删除的人的名字\n");scanf("%s", name);//找到名字叫name的人int ret = FindByName(pc, name);//找到返回下标,找不到返回-1if (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("请输入要查找的人的姓名\n");int ret = FindByName(pc->data, name);if (ret == -1){printf("要查找的人不存在\n");return;}printf("%-20s%-5d%-5s%-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];scanf("%s", name);int ret = FindByName(pc, name);if (ret == -1){printf("要修改的人的信息不存在\n");return;}//修改的逻辑else{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");}}
static int sort_by_name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}void SortContact(Contact* pc)
{if (pc->sz == 0){printf("一个人没有你排什么顺序,啊小丑!\n");}qsort(pc->data, pc->sz, sizeof((pc->data)[0]), sort_by_name);ShowContact(pc);
}

2.11 contact.h

#define _CRT_SECURE_NO_WARNINGS 
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//类型的声明
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100typedef 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[100];int sz;//人的信息个数
}Contact;//初始化通讯录
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);

相关文章:

简易实现通讯录(1.0)

前言 我们还是像以前一样,分为三个文件来书写,分别是contact.h,contact.c,test.c 分别用来声明函数,实现函数和测试函数功能,现在就让我们开始吧. 1.基本逻辑 首先我们定义通讯录里的数据,我们定义为结构体 typedef struct PeoInfo {char name[NAME_MAX];int age;char sex[SEX_…...

CSS笔记——触发式动画Transition、主动式动画Animation、Transfrom 动画、CSS 3D 动画、阴影和滤镜样式

CSS动画 一、触发式动画Transition transition过渡动画&#xff0c;一般配合伪类使用 属性值&#xff1a; transition-duration&#xff1a; 指定过渡效果的持续时间&#xff0c;以秒或毫秒为单位。 transition-timing-function&#xff1a; 指定过渡效果的时间函数&#xff…...

软件测试之Web安全测试详解

前言 随着互联网时代的蓬勃发展&#xff0c;基于Web环境下的应用系统、应用软件也得到了越来越广泛的使用。 目前&#xff0c;很多企业的业务发展都依赖于互联网&#xff0c;比如&#xff0c;网上银行、网络购物、网络游戏等。但&#xff0c;由于很多恶意攻击者想通过截获他人…...

MYSQL binlog

为了防止 binlog 文件过大导致无可用的磁盘空间&#xff0c;MySQL 提供了一个系统变量用来配置过期时间。 MySQL5.7 &#xff1a;expire_logs_days&#xff0c;精确度为天&#xff1b; MySQL8.0 &#xff1a;binlog_expire_logs_seconds&#xff0c;精确度为秒。 SET GLOBAL bi…...

Web 基础概念

自己总结的web前端知识体系大全 基础概念 DOM DOM是什么意思-前端入门_dom是什么意思啊_猿说前端的博客-CSDN博客 DOM的含义&#xff1a; DOM称为文件对象模型&#xff08;DocumentObjectModel&#xff0c;简称DOM&#xff09;&#xff0c;是W3C组织推荐的处理可扩展置标语言的…...

谈谈最近招人的感受!

最近折腾新的项目&#xff0c;面试了很多实习生小伙伴&#xff0c;我说说我的一些「面试」感受&#xff0c; 虽然是一个老生常谈的话题&#xff0c;但是依然提一下。 准时很重要&#xff1a;提前一点时间&#xff0c;踩个点&#xff0c;别迟到&#xff0c;面试的过程中由于每个…...

【日常业务开发】Java调用第三方http接口的常用方式

【日常业务开发】Java调用第三方http接口的常用方式 概述Java调用第三方http接口的方式通过JDK网络类Java.net.HttpURLConnection通过apache common封装好的HttpClient通过Apache封装好的CloseableHttpClient通过OkHttp通过Spring的RestTemplate通过hutool的HttpUtil 总结 概述…...

【大数据开发技术】实验04-HDFS文件创建与写入

文章目录 一、实验目标二、实验要求三、实验内容四、实验步骤 一、实验目标 熟练掌握hadoop操作指令及HDFS命令行接口掌握HDFS原理熟练掌握HDFS的API使用方法掌握单个本地文件写入到HDFS文件的方法掌握多个本地文件批量写入到HDFS文件的方法 二、实验要求 给出主要实验步骤成…...

中国制造让苹果跪服,将再增加一家中国高科技供应商

日前产业链人士指出由于京东方的OLED面板有力地制衡韩国面板厂商三星和LGD&#xff0c;促使他们降价&#xff0c;而且技术也不错&#xff0c;因此正计划再引入一家中国OLED面板厂商&#xff0c;以进一步促进OLED面板的竞争。 早期苹果的OLED面板完全由三星供应&#xff0c;由此…...

港卡开户感想(2023-8)

目录 银行列表预约开户总体原则外资行本地行内资行补充 选择落地点酒店及转换插头国际漫游换港币成行下一步 - 保险附录整理的银行资料 2023年8月份去了趟香港做银行开户, 整理如下供参考. 银行列表 https://www.hkma.gov.hk/gb_chi/smart-consumers/account-opening/contact-…...

机器学习第十一课--K-Means聚类

一.聚类的概念 K-Means算法是最经典的聚类算法&#xff0c;几乎所有的聚类分析场景&#xff0c;你都可以使用K-Means&#xff0c;而且在营销场景上&#xff0c;它就是"King"&#xff0c;所以不管从事数据分析师甚至是AI工程师&#xff0c;不知道K-Means是”不可原谅…...

Java on Azure Tooling 8月更新|以应用程序为中心的视图支持及 Azure 应用服务部署状态改进

作者&#xff1a;Jialuo Gan - Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎阅读 Java on Azure 工具的八月更新。在本次更新中&#xff0c;我们将推出新的以应用程序为中心的视图支持&#xff0c;帮助开发人员在一个项…...

论文笔记:ST2Vec: Spatio-Temporal Trajectory SimilarityLearning in Road Networks

2022 KDD 1 intro 现有的轨迹相似性学习方案强调空间相似性而忽视了时空轨迹的时间维度&#xff0c;这使得它们在有时间感知的场景中效率低下 如上图&#xff0c;在拼车过程中&#xff0c;T1表示司机计划的行程&#xff0c;T2和T3是两个想要搭车的人。T1和T2在空间上更接近&am…...

upload-labs靶场未知后缀名解析漏洞

upload-labs靶场未知后缀名解析漏洞 版本影响&#xff1a; phpstudy 版本&#xff1a;5.2.17 ​ 1 环境搭建 1.1 在线靶场下载&#xff0c;解压到phpstudy的www目录下&#xff0c;即可使用 https://github.com/c0ny1/upload-labs1.2 已启动&#xff1a;访问端口9000&…...

VisualStudio配置opencv

下载opencv 链接&#xff1a;https://opencv.org/releases/ 我下载的是4.7.0&#xff0c;选择windows下载。 下载成功后打开exe文件&#xff0c;选择路径安装。 配置环境变量 安装成功后找到安装目录&#xff0c;复制bin目录路径。 我的是放在了D盘 D:\Opencv4.7.0\opencv…...

如何通过git指令加入管理者仓库并提交分支(Github Gitee)

文章目录 创建GitHub、Gitee账户安装git下载gitgit基础配置 管理者创建gitee仓库新建仓库配置公钥 管理者管理仓库开发者通过git指令提交git提交错误原因&#xff1a; 创建GitHub、Gitee账户 GitHub&#xff1a; https://github.com/ Gitee &#xff1a; https://gitee.com/ …...

LuatOS-SOC接口文档(air780E)-- fastlz - FastLZ压缩

示例 -- 与miniz库的差异 -- 内存需求量小很多, miniz库接近200k, fastlz只需要32k原始数据大小 -- 压缩比, miniz的压缩比要好于fastlz-- 准备好数据 local bigdata "123jfoiq4hlkfjbnasdilfhuqwo;hfashfp9qw38hrfaios;hfiuoaghfluaeisw" -- 压缩之 local cdata …...

MySQL表的增删改查(进阶)

一 、数据库约束 NOT NULL - 指示某列不能存储 NULL 值。 UNIQUE - 保证某列的每行必须有唯一的值。 DEFAULT - 规定没有给列赋值时的默认值。 PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。 确保某列&#xff08;或两个列多个列的结合&#xff09;有唯一标识&#xff0c; 有…...

Greenplum实用工具-gpfdist

注&#xff1a;本文翻译自https://docs.vmware.com/en/VMware-Greenplum/7/greenplum-database/utility_guide-ref-gpfdist.html 向Greenplum数据库段提供数据文件或从数据库段写入数据文件。 语法 gpfdist [-d <directory>] [-p <http_port>] [-P <last_http…...

axios和fetch的区别

axios和fetch都是用于发起HTTP请求的工具&#xff0c;但是它们有一些区别&#xff1a; 语法和用法&#xff1a;axios是一个基于Promise的HTTP客户端&#xff0c;具有更简洁和直观的语法&#xff0c;可以方便地发送GET、POST、PUT等各种请求&#xff0c;并提供了更多的请求配置选…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...