基于顺序表的通讯录实现

一、前言

基于已经学过的顺序表,可以实现一个简单的通讯录。

二、通讯录相关头文件

//Contact.h
#pragma once#define NAME_MAX 20
#define TEL_MAX 20
#define ADDR_MAX 20
#define GENDER_MAX 20typedef struct PersonInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PsInFo;//struct SeqList;//前置声明typedef struct SeqList Contact;//对顺序表重命名为通讯录//通讯录的初始化
void ContactInit(Contact* pcon);//通讯录的销毁
void ContactDestroy(Contact* pcon);//添加联系人
void ContactAdd(Contact* pcon);//删除联系人
void ContactDel(Contact* pcon);//查找联系人
void ContactFind(Contact* pcon);//修改联系人
void ContactModify(Contact* pcon);//展示联系人
void ContactShow(Contact* pcon);

上述代码中结构体是我们自己定义的通讯录中联系人的基本信息,通讯录中的联系人就相当于是顺序表中的一个个数据,而通讯录就相当于是顺序表;

至于后面两行代码(前置声明和重命名)需要结合以下代码来理解

//SeqList.h
#pragma once
//顺序表
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//引用通讯录的头文件来对数据类型进行重命名
#include"Contact.h"typedef PsInFo SeqDatatype;typedef struct SeqList
{SeqDatatype* arr;int size;int capacity;
}SL;//初始化顺序表
void SeqInit(SL* ps);
//销毁顺序表
void SeqDestroy(SL* ps);
//顺序表尾插
void SeqPushBack(SL* ps, SeqDatatype x);
//申请空间
void SeqCheckSpace(SL* ps);
//打印顺序表的元素
void SeqPrint(SL* ps);
//顺序表头插
void SeqPushFront(SL* ps, SeqDatatype x);
//顺序表尾删
void SeqPopBack(SL* ps);
//顺序表头删
void SeqPopFront(SL* ps);
//指定位置前插入数据
void SeqInsert(SL* ps, int pos, SeqDatatype x);
//删除指定位置的数据
void SeqErase(SL* ps, int pos);
//寻找数据(以下标的形式返回)
//int SeqFind(SL s, SeqDatatype x);

这是顺序表的头文件,我们为了将联系人PsInFo定义为新的数据类型需要引用Contact.h的头文件,这是因为联系人是在Contact.h中定义的;所以现在回到第一段本文展示的代码中的那两行代码(前置声明和重命名),我们为了让SeqList等同于Contact,需要重命名,但是此时要使用SeqList不能直接包含SeqList.h这个头文件,这时因为头文件不能互相包含,此时我们需要进行前置声明,也就是struct SeqList; 可以直接结合起来写成typedef struct SeqList Contact;

值得注意的是,这里不能写成typedef SL Contact;因为这相当于没有进行前置声明。解释:虽然在顺序表头文件中,typedef strcut SeqList{·······}SL 看似是结构体和SL一起定义的,但实际上是结构体先定义的,也就是说,在这个结构体未定义的时候就使用SL是非法的,在Contact.h中写成typedef SL Contact; 就是遇到了这种错误,所以要进行前置声明,这样就能规避这种问题。

三、通讯录的具体实现

1、初始化

//初始化通讯录
void ContactInit(Contact* pcon)
{assert(pcon);SeqInit(pcon);
}

2、销毁

//通讯录销毁
void ContactDestroy(Contact* pcon)
{assert(pcon);SeqDestroy(pcon);
}

3、添加联系人

//添加联系人
void ContactAdd(Contact* pcon)
{assert(pcon);SeqCheckSpace(pcon);PsInFo info;//定义一个联系人printf("输入联系人姓名:\n");scanf("%s", info.name);printf("输入联系人性别:\n");scanf("%s", info.gender);printf("输入联系人年龄:\n");scanf("%d", &info.age);printf("输入联系人电话:\n");scanf("%s", info.tel);printf("输入联系人地址:\n");scanf("%s", info.addr);SeqPushBack(pcon,info);
}

 把联系人当成顺序表中的数据,先把这个数据赋予确定的数值,在这里相当于是给联系人输入一个个属性(姓名、性别、年龄······),最后进行顺序表尾插的操作;

4、返回联系人下标

int FindByName(Contact* pcon,char name[])
{for (int i = 0; i < pcon->size; i++){if (strcmp(name, pcon->arr[i].name)==0){return i;}}return -1;
}

这个函数是通过姓名比较的方式来返回即将进行一系列操作的联系人的下标 

5、删除联系人

//删除联系人
void ContactDel(Contact* pcon)
{assert(pcon);assert(pcon->size);char name[NAME_MAX];printf("输入要删除的联系人姓名:\n");scanf("%s", name);int rsl=FindByName(pcon,name);if (rsl == -1){printf("你要删除的联系人不存在\n");}else{SeqErase(pcon, rsl);}
}

首先判断这个通讯录里面有没有联系人,没有联系人则断言错误,无法删除。接着要输入一个联系人姓名,再在通过FindByName这个通讯录里面进行遍历看是否有没有这个联系人,如果没有接收到错误的下标,进行不了后续操作;找到了返回这个姓名的联系人的下标,然后使用SeqErase删除这个下标处的联系人;

6、查找联系人

//查找联系人
void ContactFind(Contact* pcon)
{assert(pcon);char name[NAME_MAX];printf("输入要查找的联系人姓名:\n");scanf("%s", name);int rsl = FindByName(pcon, name);if (rsl == -1){printf("你要查找的联系人不存在\n");}else{printf("%s""%s""%s""%s""%s", "姓名 ", "性别 ", "年龄 ", "电话 ", "地址 ");printf("\n");printf("%s ""%s ""%d ""%s ""%s ", pcon->arr[rsl].name, pcon->arr[rsl].gender, pcon->arr[rsl].age, pcon->arr[rsl].tel, pcon->arr[rsl].addr);printf("\n");}
}

查找联系人不同于返回联系人下标,它要展示出所查找的这个联系人的相关信息;

7、修改联系人信息

//修改联系人
void ContactModify(Contact* pcon)
{assert(pcon);char name[NAME_MAX];printf("输入要修改信息的联系人姓名:\n");scanf("%s", name);int rsl = FindByName(pcon, name);if (rsl == -1){printf("你要修改信息的联系人不存在\n");}else{printf("开始输入新的联系人信息\n");printf("输入联系人姓名:\n");scanf("%s", pcon->arr[rsl].name);printf("输入联系人性别:\n");scanf("%s", pcon->arr[rsl].gender);printf("输入联系人年龄:\n");scanf("%d", &pcon->arr[rsl].age);printf("输入联系人电话:\n");scanf("%s", pcon->arr[rsl].tel);printf("输入联系人地址:\n");scanf("%s", pcon->arr[rsl].addr);}
}

同样的,先通过姓名的比较来判断该联系人存不存在,若是有则重新在此联系人下标处出入相关信息;

8、展示联系人

//展示联系人
void ContactShow(Contact* pcon)
{assert(pcon);printf("%s""%s""%s""%s""%s", "姓名 ", "性别 ", "年龄 ", "电话 ", "地址 ");printf("\n");for (int i = 0; i < pcon->size; i++){printf("%s ", pcon->arr[i].name);printf("%s ", pcon->arr[i].gender);printf("%d ", pcon->arr[i].age);printf("%s ", pcon->arr[i].tel);printf("%s ", pcon->arr[i].addr);printf("\n");}
}

通过遍历通讯录来展翅一个一个联系人的相关信息。

四、设置操作面板

#include"Contact.h"
#include"SeqList.h"void menu()
{printf("********** 1.增加联系人**********\n");printf("********** 2.删除联系人**********\n");printf("********** 3.查找联系人**********\n");printf("********** 4.修改联系人**********\n");printf("********** 5.展示联系人**********\n");printf("********** 6.销毁通讯录**********\n");printf("********** 0.退出      **********\n");}
int main()
{menu();Contact con;ContactInit(&con);int option = -1;do{printf("输入操作数:\n");scanf_s("%d", &option);switch (option){case 1:ContactAdd(&con);break;case 2:ContactDel(&con);break;case 3:ContactFind(&con);break;case 4:ContactModify(&con);break;case 5:ContactShow(&con);break;case 6:ContactDestroy(&con);break;case 0:printf("退出\n");return;default:printf("输入错误,重新选择\n");}} while (option);return 0;
}

  


完。

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

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

相关文章

pycharm如何使用jupyter

目录 配置jupyter新建jupyter文件别人写的方法&#xff08;在pycharm种安装&#xff0c;在网页中使用&#xff09; pycharm专业版 配置jupyter 在pycharm终端启动一个conda虚拟环境&#xff0c;输入 conda install jupyter会有很多前置包需要安装&#xff1a; 新建jupyter…

VScode将界面语言设置为中文

1. 点击左侧的扩展图标&#xff0c;打开侧边栏“EXTENSIONS”面板。 2. 在搜索框中输入“Chinese”&#xff0c;查找出“中文简体”插件&#xff0c;点击“install”按钮。 3. 等待插件安装完成&#xff0c;点击右下角“restart”按钮&#xff0c;从而重新启动Vscode。

计算机网络——数据链路层(以太网扩展、虚拟局域网、高速以太网)

在许多情况下&#xff0c;我们希望把以太网的覆盖范围扩展。本节先讨论在物理层把以太网扩展&#xff0c;然后讨论在数据链路层把以太网扩展。这种扩展的以太网在网络层看来仍然是一个网络。 在物理层扩展以太网 现在&#xff0c;扩展主机和集线器之间的距离的一种简单方法就是…

【ARMv8/v9 GIC 系列 1.5 -- Enabling the distribution of interrupts】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 Enabling the distribution of interruptsGIC Distributor 中断组分发控制CPU Interface 中断组分发控制Physical LPIs 的启用Summary Enabling the distribution of interrupts 在ARM GICv3和GICv4体系结构中&#xff0c;中断分发…

python sklearn机械学习-数据预处理

&#x1f308;所属专栏&#xff1a;【机械学习】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您…

关于string的‘\0‘与string,vector构造特点加部分特别知识点的讨论

目录 前言&#xff1a; 问题一&#xff1a;关于string的\0问题讨论 问题二&#xff1a;C标准库中的string内存是分配在堆上面吗&#xff1f; 问题三&#xff1a;string与vector的capacity大小设计的特点 问题四&#xff1a;string的流提取问题 问题五&#xff1a;迭代器失…

【Python】组合数据类型:序列,列表,元组,字典,集合

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️Python】 文章目录 前言组合数据类型序列类型序列常见的操作符列表列表操作len()append()insert()remove()index()sort()reverse()count() 元组三种序列类型的区别 集合类型四种操作符集合setfrozens…

Vue表单输入绑定v-model

表单输入绑定 在前端处理表单时&#xff0c;我们常常需要将表单输入框的内容同步给Javascript中相应的变量。手动连接绑定和更改事件监听器可能会很麻&#xff0c;v-model 指令帮我们简化了这一步骤。 <template><h3>表单输入绑定</h3><hr> <inpu…

C/C++连接MySQL

今天刚学习了MySQL,于是去尝试能否让C/C连接上MySQL,一番尝试后也是成功了&#xff0c;把经验分享给大家&#xff01; 1.首先我们需要找到MySQL所在的目录下&#xff0c;一般默认安装路径都在C:\Program Files\MySQL\MySQL Server 8.0下&#xff1b; 2.随后我们打开Visual Stu…

[go-zero] 简单微服务调用

文章目录 1.注意事项2.服务划分及创建2.1 用户微服务2.2 订单微服务 3.启动服务3.1 etcd 服务启动3.2 微服务启动3.3 测试访问 1.注意事项 go-zero微服务的注册中心默认使用的是Etcd。 本小节将以一个订单服务调用用户服务来简单演示一下&#xff0c;其实订单服务是api服务&a…

“郭有才”商标主要类别都已被注册!

前阵山东网红“郭有才”火遍大江北&#xff0c;当然少不了许多想去申请注册“郭有才”商标名称的&#xff0c;普推商标知产老杨检索&#xff0c;发现“郭有才”商标申请了43个类别&#xff0c;基本上类别都被申请注册&#xff0c;已注册的商标大多是在“郭有才”火之前申请注册…

NDVI数据集提取植被覆盖度FVC

植被覆盖度FVC 植被覆盖度&#xff08;Foliage Vegetation Cover&#xff0c;FVC&#xff09;是指植被冠层覆盖地表的面积比例&#xff0c;通常用来描述一个区域内植被的茂密程度或生长状况。它是生态学、环境科学以及地理信息系统等领域的重要指标&#xff0c;对于理解地表能…

数据结构之“栈”(全方位认识)

&#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;数据结构 前言 栈是一种数据结构&#xff0c;具有" 后进先出 "的特点 或者也可见说是 ” 先进后出 “。大家一起加油吧冲冲冲&#xff01;&#xff01; …

react 项目中预防xss攻击的插件 dompurify

一、安装 $ yarn add dompurify $ yarn add --dev types/dompurify 二、使用 import DOMPurify from dompurify;// 1、处理&#xff1a; DOMPurify.sanitize(htmlContent)// 2、之后放进 dangerouslySetInnerHTML dangerouslySetInnerHTML{{ __html: cleanHTML }} 如&#…

Android Studio Run窗口中文乱码解决办法

Android Studio Run窗口中文乱码解决办法 问题描述&#xff1a; AndroidStudio 编译项目时Run窗口中文乱码&#xff0c;如图&#xff1a; 解决方法&#xff1a; 依次打开菜单&#xff1a;Help--Edit Custom VM Options&#xff0c;打开studio64.exe.vmoptions编辑框&#xf…

c/c++ 程序运行的过程分析

c/c编译基础知识 GNU GNU&#xff08;GNU’s Not Unix!&#xff09;是一个由理查德斯托曼&#xff08;Richard Stallman&#xff09;在1983年发起的自由软件项目&#xff0c;旨在创建一个完全自由的操作系统&#xff0c;包括操作系统的内核、编译器、工具、库、文本编辑器、邮…

ROS——坐标系管理、监听与广播、常用可视化工具

坐标系管理 TF功能包 小海龟追踪实验 ros版本(20.04)的tf安装命令: sudo apt-get install ros-noetic-turtle-tf 解决因python版本出现的无法生成跟随海龟&#xff1a; sudo ln -s /usr/bin/python3 /usr/bin/python ( -s 软链接,符号链接) ln命令&#xff08;英文全拼&#…

7 动态规划

下面的例子不错&#xff1a; 对于动态规划&#xff0c;能学到不少东西&#xff1b; 你要清楚每一步都在做什么&#xff0c;划分细致就能够拆解清楚&#xff01; xk. - 力扣&#xff08;LeetCode&#xff09; labuladong的算法笔记-动态规划-CSDN博客 动态规划是一种强大的算法…

JDK都出到20多了,你还不会使用JDK8的Stream流写代码吗?

目录 前言 Stream流 是什么&#xff1f; 为什么要用Steam流 常见stream流使用案例 映射 map() & 集合 collect() 单字段映射 多字段映射 映射为其他的对象 映射为 Map 去重 distinct() 过滤 filter() Stream流的其他方法 使用Stream流的弊端 前言 当你某天看…

【图解大数据技术】Hive、HBase

【图解大数据技术】Hive、HBase Hive数据仓库Hive的执行流程Hive架构数据导入Hive HBaseHBase简介HBase架构HBase的列式存储HBase建表流程HBase数据写入流程HBase数据读取流程 Hive Hive是基于Hadoop的一个数据仓库工具&#xff0c;Hive的数据存储在HDFS上&#xff0c;底层基于…