通讯录(C 语言)
目录
- 一、通讯录设计思路
- 1. 伪代码设计思路
- 2. 代码设计思路
- 二、代码实现
- 三、程序运行演示
- 四、整体分析
一、通讯录设计思路
1. 伪代码设计思路
通讯录可以用来存储 100 个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。
提供方法:
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 以名字排序所有联系人
2. 代码设计思路
通过对上述伪代码的分析,我们使用结构体 info_person 来表示个人信息。
// 个人信息结构声明
typedef struct info_person
{char name[20]; // 姓名char sex[5]; // 性别size_t age; // 年龄char phone[12]; // 电话char address[40]; // 住址
}info_person;
接着再使用一个结构体 ContacksList 来表示通讯录,该通讯录包含一个结构体 info_person 数组,大小为 100,用来存储 100 个人的信息。此外还应该包含一个 size_t 类型的成员 size 用来表示当前存储个人信息的数量,这也方便了上述伪代码中要求的方法设计。
// 常量声明
#define SIZE_INFO 100// 通讯录结构声明
typedef struct ContacksList
{info_person infos[SIZE_INFO];size_t size;
}ContacksList;
下面就是使用有意义的函数名来表示上述方法。
// 方法// 1. 添加联系人信息
void AddContack(ContacksList* cl);// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl, char* name);// 3. 查找指定联系人信息
void FindContack(const ContacksList* cl, char* name);// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl, char* name);// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl);// 6. 清空所有联系人
void ClearContack(ContacksList* cl);// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl);
以上就是头文件 ContacksList.h 包含的基本内容,剩下的就是方法的实现和代码的测试。
二、代码实现
整体代码分成三个文件:头文件 ContacksList.h,方法定义文件 ContacksList.c,测试文件 test.c。由于头文件在前面已经给出,下面就只给出剩下两个文件。
方法定义文件 ContacksList.c
// 头文件
#include "ContacksList.h"
#include <assert.h>
#include <string.h>// 方法// 1. 添加联系人信息
void AddContack(ContacksList* cl)
{assert(cl);// 通讯录已满if (CAPACITY == cl->size){printf("通讯录已满,添加失败!\n");return;}// 添加// // 输入联系人的相关信息info_person tmp;printf("请输入联系人的信息->");printf("姓名: ");scanf("%s", tmp.name);printf("性别: ");scanf("%s", tmp.sex);printf("年龄: ");scanf("%zd", &tmp.age);printf("电话: ");scanf("%s", tmp.phone);printf("地址: ");scanf("%s", tmp.address);// 拷贝cl->infos[cl->size] = tmp;// 人数 +1++cl->size;printf("添加成功!\n");
}// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl)
{assert(cl);// 删除//// 查找指定联系人char name[20];printf("请输入删除人的姓名: ");scanf("%s", name);int i = FindContack(cl, name);// 找到了if (-1 != i){// 把该位置往后的联系人往前移while (i < cl->size - 1){// 前移cl->infos[i] = cl->infos[i + 1];// 下一个++i;}// 联系人 -1--cl->size;printf("删除成功!\n");}else{printf("删除失败!\n");}
}// 3. 查找指定联系人信息
int FindContack(const ContacksList* cl, char* name)
{assert(cl);// 通讯录为空if (0 == cl->size)return -1;// 输入查找人的姓名char tmp[20] = { 0 };if (NULL == name){name = tmp;printf("请输入查找人的姓名: ");scanf("%s", name);}// 查找int i;for (i = 0; i < cl->size; ++i){// 找到if (strcmp(cl->infos[i].name, name) == 0){return i;}}// 没找到return -1;
}// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl)
{assert(cl);// 查找指定联系人char name[20];printf("请输入修改人的姓名: ");scanf("%s", name);int i = FindContack(cl, name);// 找到了if (-1 != i){// 输入联系人修改后的相关信息info_person tmp;printf("请输入联系人的信息->");printf("姓名: ");scanf("%s", tmp.name);printf("性别: ");scanf("%s", tmp.sex);printf("年龄: ");scanf("%zd", &tmp.age);printf("电话: ");scanf("%s", tmp.phone);printf("地址: ");scanf("%s", tmp.address);// 修改cl->infos[i] = tmp;printf("修改成功!\n");}else{printf("修改失败!\n");}
}// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl)
{assert(cl);// 标题行printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");// 输出int i;for (i = 0; i < cl->size; ++i){printf("%-10s%-8s%-8zd%-15s%-10s\n", cl->infos[i].name, cl->infos[i].sex, cl->infos[i].age, cl->infos[i].phone, cl->infos[i].address);}
}// 6. 清空所有联系人
void ClearContack(ContacksList* cl)
{assert(cl);// 清空cl->size = 0;
}// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl)
{assert(cl);// 冒泡排序int i;for (i = 0; i < cl->size - 1; ++i){int j;for (j = 0; j < cl->size - 1 - i; ++j){// 相邻比较if (strcmp(cl->infos[j].name, cl->infos[j + 1].name) > 0){// 交换info_person tmp = cl->infos[j];cl->infos[j] = cl->infos[j + 1];cl->infos[j + 1] = tmp;}}}printf("按名字身升序排序成功!\n");
}
测试文件 test.c
// 头文件
#include "ContacksList.h"// 菜单
void menu()
{printf("****************************************************\n");printf("***********1. Add 2. Delete *************\n");printf("***********3. Find 4. Modify *************\n");printf("***********5. Print 6. Clear *************\n");printf("***********7. Sort 0. Exit *************\n");printf("****************************************************\n");
}int main()
{// 创建通讯录ContacksList cl = { {0}, 0 };// 选择操作int select = 0;int i = 0;do{// 菜单menu();// 选择printf("请选择: ");scanf("%d", &select);switch (select){case 1:AddContack(&cl);break;case 2:DeleteContack(&cl);break;case 3:i = FindContack(&cl, NULL);printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s%-8s%-8zd%-15s%-10s\n", cl.infos[i].name, cl.infos[i].sex, cl.infos[i].age, cl.infos[i].phone, cl.infos[i].address);break;case 4:ModifyContack(&cl);break;case 5:PrintContack(&cl);break;case 6:ClearContack(&cl);break;case 7:SortByName(&cl);break;case 0:printf("退出通讯录!\n");break;default:printf("选择错误,请重新选择!\n");break;}} while (select);return 0;
}
三、程序运行演示

四、整体分析
该通讯录是一个静态通讯录,容量是固定的,当数据超出容量时不够存储,当数据少于容量时造成空间的浪费。后面作者会把该通讯录升级为动态通讯录,当容量不够的时候会进行增容。
在方法实现中,删除指定联系人函数 DeleteContack() 和修改指定联系人函数 ModifyContack() 都需要先找到指定的联系人,所以可以稍微修改一下查找指定联系人函数 FindContack(),然后再前面两个函数中调用该函数,这样就减少了代码的冗余。删除操作需要判断通讯录是否为空,插入操作需要判断通讯录是否已满。
当然读者可以自行根据需要进行修改,这里只提供一个大概思路和基础功能的实现。
相关文章:
通讯录(C 语言)
目录 一、通讯录设计思路1. 伪代码设计思路2. 代码设计思路 二、代码实现三、程序运行演示四、整体分析 一、通讯录设计思路 1. 伪代码设计思路 通讯录可以用来存储 100 个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。 提供方法&#x…...
对比Java和TypeScript中的服务注册和查找机制
文章目录 一、Java中的服务注册和查找二、TypeScript中的服务注册和查找2.1 使用依赖注入(DI)框架2.2 injectable原理2.3 使用TypeScript的反射系统实现依赖注入 三、优缺点分析3.1 Java的ServiceLoader3.2 TypeScript的服务注册和查找 四、结论 在构建大…...
Flutter 主流常用第三方库、插件收集
一、Flutter 学习资料 FlutterFlutter官网Flutter中文网咸鱼技术掘金Flutter专栏 Flutter - Dart中(.)、(..)、(...)语法使用_flutter ...-CSDN博客 Flutter pubspec.yaml 配置文件_flutter yaml配置git-CSDN博客 Flutter 添加 example流程_建flutter 工程 怎么自动有example-C…...
【在Linux世界中追寻伟大的One Piece】多路转接select
目录 1 -> I/O多路转接之select 1.1 -> 初识select 1.2 -> select函数原型 1.3 -> 关于fd_set结构 1.4 -> 关于timeval结构 2 -> 理解select执行过程 2.1 -> Socket就绪条件 2.2 -> select特点 2.3 -> select缺点 3 -> select使用示例…...
补一下 二维 平面直角坐标系 到三维
上一篇帖子写到 二维的平面直角坐标系,是那样的,这次补充一下三维的。首先需要,安装一个包,如下: 然后,把参数输入,输入这个坐标系的参数,如下: 这样就可以输出如下的三…...
如何学习Python编程?
如何学习Python编程? 了解基础概念: 学习Python的基本语法,包括变量、数据类型、运算符等。了解控制结构,如条件语句(if语句)和循环(for和while循环)。 选择学习资源: 在…...
使用EasyExcel实现导出excel文件时生成多级下拉选
前言 公司有个需求本来只涉及到两个下拉选项,后面就想能不能实现多个下拉选,当然我这里说的多个下拉选是联动的,比如省、地市、区县这种。 实现步骤 1、添加EasyExcel的Maven依赖 <dependency><groupId>com.alibaba</group…...
微信小程序 高校教材征订系统
文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 系统分为三个角色,分别是教材科、系教学秘书、教研室主任。系统主要完成功能是教材科要发布教材征订信息&am…...
从0开始的STM32 定时器(I):聊一聊基本定时器
目录 时钟源 控制器 时基单元 关于HAL库如何配置基本定时器 HAL是如何初始化我们的定时器句柄的 HAL_TIM_Base_Init 开始定时 如何处理句柄? 在我们使用STM32解决一些问题的时候,常常会遇到说:我想要以一个周期做一些事情:…...
vue常见题型(1-10)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 2.2双向绑定的原理是什么vue框架采用的是数据双向绑定的方式,由三个重要部分构成2.2.1.ViewModel2.2.2 双向绑定2.2.3.1.编译Compile2.2.3.2.依赖收集 3…...
【SpringBoot】使用注解进行XSS防御
在Spring Boot中,我们可以使用注解的方式来进行XSS防御。注解是一种轻量级的防御手段,它可以在方法或字段级别对输入进行校验,从而防止XSS攻击。 引入相关依赖 maven依赖: <!--JSR-303/JSR-380用于验证的注解 --> <de…...
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目分享——共九套(每套四十题) 岗位——芯片与器件设计工程师 岗位意向——模拟芯片 真题题目分享,完整题目,无答案(共8套) 实习岗位…...
vscode 下载慢的解决方法
下载链接示例:https://az764295.vo.msecnd.net/stable/ccbaa2d27e38e5afa3e5c21c1c7bef4657064247/code1.62.3-1637137107amd64.deb 解决方法: 把 az764295.vo.msecnd.net 替换成 vscode.cdn.azure.cn...
STM32ZET6-USART使用
一、原理说明 STM32自带通讯接口 通讯目的 通信方式: 全双工:通信时可以双方同时通信。 半双工:通信时同一时间只能一个设备发送数据,其他设备接收。 单工:只能一个设备发送到另一个设备,例如USART只有…...
es自动补全(仅供自己参考)
elasticssearch提供了CompletionSuggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询效率,对于文档中字段的类型有一些约束: 查询类型必须是:completion 字段内容是多个补全词条形成的数组 P…...
13-综合排序:Function Score Query 优化算分
使用了 function_score 查询来根据某个字段的值对查询结果进行打分。以下是该查询的主要部分: query: 包含了实际执行搜索的部分,在这里包括一个 multi_match 查询。 multi_match:用于在多个字段上执行相同的查询。 query:设置…...
鸿蒙应用App测试-专项测试(DevEco Testing)
注意:大家记得先学通用测试在学专项测试 鸿蒙应用App测试-通用测试-CSDN博客 注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注&am…...
RabbitMQ设置消息过期时间
RabbitMQ设置消息过期时间 1、过期消息(死信)2、设置消息过期的两种方式2.1、设置单条消息的过期时间2.1.1、配置文件application.yml2.1.2、配置类RabbitConfig2.1.3、发送消息业务类service(核心代码)2.1.4、启动类2.1.5、依赖文…...
大数据-209 数据挖掘 机器学习理论 - 梯度下降 梯度下降算法调优
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
粒子群优化双向深度学习!PSO-BiTCN-BiGRU-Attention多输入单输出回归预测
粒子群优化双向深度学习!PSO-BiTCN-BiGRU-Attention多输入单输出回归预测 目录 粒子群优化双向深度学习!PSO-BiTCN-BiGRU-Attention多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现PSO-BiTCN-BiGRU-Attention粒子…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
