哲♂学家带你用顺序表实现通讯录

实现通讯录能使我们进一步加深对顺序表的理解,接下来就由本哲♂学家带你手把手实现通信录。

其中需要用到顺序表的知识可以点击下面链接了解:http://t.csdnimg.cn/9SjGd话不多说,我们♂开始吧。

一、通讯录头文件声明

由于我们前面已经写过顺序表其头文件我们可以直接用这里只展示seqlist的头文件

seqlist.h:

#pragma once//防止头文件二次引用
typedef struct PersonInfo SLDataType;//方便后续该存储类型
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"contact.h"
typedef struct seqlist
{SLDataType* arr;//存放数据的数组int size;//有效元素个数int capacity;//空间的大小
}SL;
// 初始化和销毁
void SLInit(SL * ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
//找到指定位置的数据
int SLFind(SL* ps, SLDataType x);

contact.h:

#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//因为头文件不能相互包含,所以用前置声明
typedef struct SeqList contact;
//用户数据
typedef struct PersonInfo{char name[NAME_MAX];//名字char sex[SEX_MAX];//性别int age;//年龄char tel[TEL_MAX];//电话char addr[ADDR_MAX];//地址
}PeoInfo;
//初始化通讯录void InitContact(contact* con);//实际上是对顺序表初始化//添加通讯录数据void AddContact(contact* con);//删除通讯录数据void DelContact(contact* con);//展示通讯录数据void ShowContact(contact* con);//查找通讯录数据void FindContact(contact* con);//修改通讯录数据void ModifyContact(contact* con);//销毁通讯录数据void DestroyContact(contact* con);

值得注意的是因为头文件不能相互包含所以只能前置声明我们创建的SeqList结构体。

二、函数实现:

首先我们要明确通讯录实际上是顺序表,只不过其内容是结构,对通讯录的操作,实际上是对顺序表的操作。

1、初始化与销毁

前面我们知道,通讯录本质上是顺序表,所以对通讯录的初始化和销毁,实际上就是对顺序表的初始化和销毁:

//初始化通讯录
void InitContact(contact* con)//实际上是对顺序表初始化
{SLInit(con);
}
//销毁通讯录
void DestroyContact(contact* con)
{void SLDestroy(SL * ps);
}

2、添加通讯录信息

//添加通讯录信息
void ContactAdd(contact* con)
{//获取用户输入的内容:姓名+性别+年龄+电话+地址PeoInfo info;//创建顺序表的元素printf("请输入要添加的联系人姓名:\n");scanf("%s", info.name);printf("请输入要添加的联系人性别:\n");scanf("%s", info.sex);printf("请输入要添加的联系人年龄:\n");scanf("%d", &info.age);printf("请输入要添加的联系人电话:\n");scanf("%s", info.tel);printf("请输入要添加的联系人住址:\n");scanf("%s", info.addr);//往通讯录中添加联系人数据,实际上就是尾部插入。SLPushBack(con, info);//SLPushBack中带有空间大小检查功能这不用考虑空间大小问题
}

实际上,我们只不过将顺序表的成员改成了结构体而已,所以要将结构体插入(一定要捋清楚这个关系)。 

3、删除通讯录信息

如果是一个普通的数组,我们只需要将要删除的下标穿过去就好了,但是这个是要删除结构体,我们可以通过访问结构体包含的名字成员对比,来找到元素下标删除数据:

//只是删除数据的辅助函数,不是找数据的函数
int FindByName(contact* con, char name[])
{for (int i = 0; i < con->size; i++){if (0 == strcmp(con->arr[i].name, name)){//找到了return i;}}//没有找到return -1;
}
//删除通讯录数据
void DelContact(contact* con)
{printf("请输入要删除的名字:");char dename[NAME_MAX];scanf("%s", dename);int find = FindByName(con, dename);if (find < 0){printf("要删除的联系人数据不存在!\n");return;//不存在直接跳出函数;}//要删除的联系人数据存在--->知道了要删除的联系人数据对应的下标SLErase(con, find);printf("删除成功!\n");
}

 

代码显示没有任何问题。 

4、展示通讯录数据

这个就直接上代码了,非常简单

void ShowContact(contact* con)
{//表头:姓名  性别 年龄 电话  地址printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");//遍历通讯录,按照格式打印每个联系人数据for (int i = 0; i < con->size; i++){printf("%3s %3s %3d %3s %3s\n", //手动调整一下格式con->arr[i].name,con->arr[i].sex,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}
}

5、查找通讯录数据

整体思路和前面的删除数据的辅助函数十分类似,或者直接可以使用上面的辅助函数。直接上代码:

void FindContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要查找的联系人数据不存在!\n");return;}printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%3s %3s %3d %3s %3s\n",con->arr[find].name,con->arr[find].sex,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);
}

同样的代码没有任何问题。

6、修改指定数据

与删除数据时整体思路一致,直接上代码:

void ModifyContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要查找的联系人数据不存在!\n");return;}//直接修改不用创建临时变量printf("请输入要修改的联系人姓名:\n");scanf("%s", con->arr[find].name);printf("请输入要修改的联系人性别:\n");scanf("%s", con->arr[find].sex);printf("请输入要修改的联系人年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入要修改的联系人电话:\n");scanf("%s", con->arr[find].tel);printf("请输入要修改的联系人住址:\n");scanf("%s", con->arr[find].addr);}

代码没有任何问题 

7、关于永久保存问题

以上所写的信息在退出程序后是无法保存的,要永久保存我们得使用文件操作函数来达到这个目的。

1、信息导入:

//从文件中读取数据
void LoadContact(contact* con) 
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL) {perror("fopen error!\n");return;}//循环读取⽂件数据PeoInfo info;while (fread(&info, sizeof(PeoInfo), 1, pf)){SLPushBack(con, info);}printf("历史数据导入通讯录成功!\n");
}

值得注意的一点是fread导入的是二进制文件所以我们是无法修改文件达到导入信息的目的

2、信息保存

void SaveContact(contact* con) 
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL) {perror("fopen error!\n");return;}//将通讯录数据写⼊⽂件for (int i = 0; i < con->size; i++){fwrite(con->arr + i, sizeof(PeoInfo), 1, pf);}printf("通讯录数据保存成功!\n");
}

8、控制台的实现

#include"seqlisr.h"
//#include"contact.h"
void menu()
{printf("******************通讯录******************\n");printf("*******1.增加联系人   2.删除联系人********\n");printf("*******3.修改联系人   4.查找联系人********\n");printf("*******5.展示联系人   6.保存数据  ********\n");printf("*******7.导入数据     0.   退出  *********\n");printf("******************************************\n");
}int main()
{int op = -1;contact con;InitContact(&con);do {menu();printf("请选择您的操作:\n");scanf("%d", &op);//要根据对应的op执行不同的操作switch (op){case 1:AddContact(&con);break;case 2:DestroyContact(&con);break;case 3:ModifyContact(&con);break;case 4:FindContact(&con);break;case 5:ShowContact(&con);break;case 6:SaveContact(&con);break;case 7:LoadContact(&con);break;case 0:printf("退出通讯录....\n");break;default:printf("输入错误,请重新选择您的操作!\n");break;}} while (op != 0);DelContact(&con);return 0;
}

第一次运行: 

 第二次运行:

发现数据被永久保存了。 

总结:

通讯录是非常典型的顺序表使用示例,其最后的永久保存数据更是需要我们使用文件函数,代码总量也是非常大足足有400多行,需要大家好好消化。期待下一次和你们一起van♂。

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

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

相关文章

四核8g服务器价格多少钱?

2024年腾讯云4核8G服务器租用优惠价格&#xff1a;轻量应用服务器4核8G12M带宽646元15个月&#xff0c;CVM云服务器S5实例优惠价格1437.24元买一年送3个月&#xff0c;腾讯云4核8G服务器活动页面 txybk.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云4核8G服务器优惠价格 轻…

【数据结构】——二叉树的递归实现,看完不再害怕递归

创作不易&#xff0c;感谢三连加支持&#xff1f;&#xff01; 一 递归理解 递归无非就是相信它&#xff0c;只有你相信它&#xff0c;你才能写好递归&#xff01;为什么&#xff1f;请往下看 在进入二叉树的实现之前&#xff0c;我们得先理解一遍递归&#xff0c;可能很多…

Android JNI 调用第三方SO

最近一个项目使用了Go 编译了一个so库&#xff0c;但是这个so里面还需要使用第三方so库pdfium, 首先在Android工程把2个so库都放好 在jni中只能使用dlopen方式&#xff0c;其他的使用函数指针的方式来调用&#xff0c;和windows dll类似&#xff0c;不然虽然编译过了但是会崩溃…

基于H2O AutoML与集成学习策略的房屋售价预测模型研究与实现

项目简述&#xff1a; 本项目采用H2O AutoML工具&#xff0c;针对加州房屋销售价格预测问题进行了深入研究与建模。项目以Kaggle提供的加州房屋 交易数据集为基础&#xff0c;通过数据清洗、特征工程、模型训练与评估等步骤&#xff0c;构建了一种基于集成学习策略的房价预测模…

Flink运行机制相关概念介绍

Flink运行机制相关概念介绍 1. 流式计算和批处理2. 流式计算的状态与容错3. Flink简介及其在业务系统中的位置4. Flink模型5. Flink的架构6. Flink的重要概念7. Flink的状态、状态分区、状态缩放&#xff08;rescale&#xff09;和Key Group8. Flink数据交换9. 时间语义10. 水位…

GrayLog日志平台的基本使用-接入jumpserver

1、jumpserver3.8.0部署 Docker 环境准备 # 安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 替换Docker 安装源为清华大学镜像站 sed -i sh…

Spring Web MVC的入门学习(一)

目录 一、什么是 Spring Web MVC 1、MVC 定义 二、学习Spring MVC 1、项目准备 2、建立连接 2.1 RequestMapping 注解的学习 2.2 RequestMapping 使用 3、请求 3.1 传递单个参数 3.2 传递多个参数 3.3 传递对象 3.4 后端参数重命名&#xff08;后端参数映射&#xf…

1111111

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

配置code-server和texlive实现网页写tex

使用overleaf太卡了&#xff0c;有云服务器或者nas小主机&#xff0c;配置自己的code-servertexlive&#xff0c;来写论文。 之前用服务器配置过自己的overleaf&#xff0c;感觉不是很好用&#xff0c;缺少东西。 一、思路 使用docker先安装一个ubuntu&#xff0c;用dockerfil…

day63 单调栈part02

503. 下一个更大元素 II 中等 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更…

【generate】如何维护一套icon组件库,直接输出svg为react component

https://github.com/ant-design/ant-design-web3/pull/761/files 实现了icon-preview(通过jsdoc, 鼠标放在组件上可以看到icon的样式)&#xff0c;因为打包方式、产物以及命名上有一些不同&#xff0c;可能需要稍加改造。 这个同步脚本应该后续也用得上&#xff0c;略加改造同步…

Macbook文件清理软件 Mac电脑清理垃圾文件怎么清理

为了维护Macbook电脑的系统健康&#xff0c;我们需要定期给电脑进行全面清理&#xff0c;清除系统垃圾文件、软件缓存和系统内存。那么好用的Macbook文件清理软件有哪些呢&#xff1f;今天就给大家介绍几款好用的电脑清理软件并介绍Mac电脑清理垃圾文件怎么清理。 一、Macbook…

29-控制流(下):iam-apiserver服务核心功能实现讲解

我们再来看下 iam-apiserver 中的核心功能实现。 这些关键代码设计分为 3 类&#xff0c;分别是应用框架相关的特性、编程规范相关的特性和其他特性。 应用框架相关的特性 应用框架相关的特性包括三个&#xff0c;分别是优雅关停、健康检查和插件化加载中间件。 优雅关停 …

基于SpringBoot和Vue的教务网络管理系统的设计与实现【附源码】

1、系统演示视频&#xff08;演示视频&#xff09; 2、需要交流和学习请联系

00-JAVA基础-注解及反射解析注解

注解 什么是注解 Java 注解&#xff08;Annotation&#xff09;是 JDK 5.0 引入的一种元素&#xff0c;用于为 Java 代码提供元数据。元数据是关于数据的数据&#xff0c;它为代码提供附加信息&#xff0c;而这些信息并不直接参与到程序的逻辑中&#xff0c;但可以被编译器或…

Spring Boot | Spring Boot的“数据访问“、Spring Boot“整合MyBatis“

目录: 一、Spring Boot”数据访问概述“二、Spring Boot”整合MyBatis”1. 基础环境搭建 (引入对应的“依赖启动器” 配置数据库的“相关参数”)① 数据准备 (导入Sql文件)② 创建项目&#xff0c;引入相应的启动器&#xff0c;编写数据库对应的“实体类”③额外添加pom.xml文…

联想 Y9000P 连接网线速度慢 的 问题解决

参考帖子&#xff1a;求助&#xff0c;拯救者Y9000P 2022 i73060版本 有线网非常慢 无线网正常【笔记本吧】_百度贴吧 问题原因&#xff1a; 网卡驱动版本不对。不能用Win11版&#xff0c;要用Win10版。 问题解决&#xff1a; 1、卸载原驱动 2、下载Win10 驱动 并安装 下载…

MFC通用静态库制作与使用

开发环境VS2013 1、新建工程&#xff0c;选择Win32 Project&#xff0c;命名&#xff0c;选择路径等 2、选择Static library &#xff0c;勾选MFC 3、点击完成。在工程中添加相应的头文件、源文件等通用功能函数或者类。 4、在其他工程引入使用。在使用的工程项目设置中Linker…

tsv、csv、xls等文件类型区别及处理(python版)

目录 前言 介绍 tsv、csv、txt的区别 读取/生成 不同格式数据文件&#xff08;python&#xff09; 一、读取/生成csv数据文件 二、读取/生成txt数据文件 三、读取/生成tsv数据文件 四、读取/生成xls数据文件 不同文件格式转化 总结 前言 考虑到进行机器学习、深度学习…

vue快速入门(五)v-show与v-if

注释很详细&#xff0c;直接上代码 上一篇 新增内容 v-if与v-show底层的区别v-if与v-show的效果 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice…