【(数据结构) —— 顺序表的应用-通讯录的实现】

(数据结构)—— 顺序表的应用-通讯录的实现

  • 一.通讯录的功能介绍
    • 1.基于动态顺序表实现通讯录
      • (1). 功能要求
      • (2).重要思考
  • 二. 通讯录的代码实现
    • 1.通讯录的底层结构(顺序表)
      • (1)思路展示
      • (2)底层代码实现(顺序表)
    • 2.通讯录上层代码实现(通讯录结构)
      • (1).思路展示
      • (2).上层代码实现(通讯录)
    • 3.通讯录代码运行展示(数据只用于测试,无实际意义)
      • (1)测试展示
      • (2)升华总结

一.通讯录的功能介绍

1.基于动态顺序表实现通讯录

C语言基础要求:结构体、动态内存管理、顺序表、文件件操作

(1). 功能要求

1)至少能够存储100个人的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系人信息
4)删除指定联系人
5)查找制定联系人
6)修改指定联系人
7)显示联系人信息

(2).重要思考

思考1】用静态顺序表和动态顺序表分别如何实现
思考2】如何保证程序结束后,历史通讯录信息不会丢失

二. 通讯录的代码实现

1.通讯录的底层结构(顺序表)

(1)思路展示

由于,通讯录是基于动态顺序表实现的,所以掌握基本的顺序表的结构代码,非常重要~!

(2)底层代码实现(顺序表)

1.

SeqList.h
#pragma once
#include"Contact.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>//typedef int SLDataType;
//更改数据类型为通讯录数据类型
//以下的方式任意选择即可
typedef struct ContactInfo SLDataType;
//typedef CInfo SLDataType;typedef struct SeqList
{SLDataType* a;int size;//当前顺序表中的数据有效个数int capacity;//顺序表的当前空间的大小
}SL;
//typedef struct SeqList SL;//对顺序表进行初始化
void SLInit(SL* ps);
void SLDestroy(SL* ps);
//头部/尾部/插入/删除
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);//任意位置/插入/删除
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);//打印
void SLPrint(SL* ps);
bool SLIsEmpty(SL* ps);//查找
bool SLFind(SL* ps, SLDataType x);

2.

SeqList.c
#include"SeqList.h"//初始化顺序表
void SLInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}
void SLDestroy(SL* ps)
{if (ps->a)free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;}void SLCheckCapacity(SL* ps)
{//空间不足以插入一个数据,需要扩容if (ps->size == ps->capacity){//扩容int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc Fail!\n");return 1;}ps->a = tmp;ps->capacity = newCapacity;}
}//尾插
void SLPushBack(SL* ps, SLDataType x)
{//判断顺序表是否为空//assert(ps->a = NULL);//暴力方式assert(ps);//柔和的方式/*if (ps->a == NULL)return;*///1)空间足够,直接插入//2)空间不够,需要扩容SLCheckCapacity(ps);//空间足够,直接插入ps->a[ps->size++] = x;
}
//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//空间足够,历史数据后移一位;for (size_t i = ps->size; i > 0; i--){ps->a[i] = ps->a[i - 1];}ps->a[0] = x;ps->size++;
}
//尾删
void SLPopBack(SL* ps)
{assert(ps);assert(!SLIsEmpty(ps));//ps->a[ps->size - 1] = 0;ps->size--;
}//头删
void SLPopFront(SL* ps)
{assert(ps);assert(!SLIsEmpty(ps));for (size_t i = 1; i < ps->size - 1; i++){//最后一次进来的是ps->a[ps->size-2]ps->a[i] = ps->a[i + 1];//pa->a[ps->size-2]=ps->a[ps->size-1]}ps->size--;
}//任意位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);//判断插入的位置是否在范围内assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);//空间足够,把pos的位置及以后的数据往后移一位//此处i<ps->size和ps->size-1都可以,但是后面的不步骤需要对应for (size_t i = ps->size; i > pos; i--){ps->a[i] = ps->a[i - 1];}/*for (size_t i = ps->size - 1; i > pos; i--){ps->a[i+1] = ps->a[i];}*/ps->a[pos] = x;ps->size++;}
//任意位置删除
void SLErase(SL* ps, int pos)
{assert(ps);assert(!SLIsEmpty(ps));assert(pos >= 0 && pos < ps->size);//pos位置及以后的数据往前移动一位for (size_t i = pos; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;}void SLPrint(SL* ps)
{for (size_t i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
bool SLIsEmpty(SL* ps)
{assert(ps);//这样是不对的,这只是判断空间是否足够//return ps->size = ps->capacity;return ps->size == 0;
}//bool SLFind(SL* ps, SLDataType x)
//{
//	scanf("%d", &x);
//	for (size_t i = 0; i < ps->size; i++)
//	{
//		if (ps->a[i] == x)
//		{
//			return true;
//		}
//	}
//	return false;
//}

3.

test.c
#include"SeqList.h"
#include"Contact.h"//void SLtest()
//{//SL sl;//SLInit(&sl);顺序表的具体操作尾插//SLPushBack(&sl, 1);//SLPushBack(&sl, 2);//SLPushBack(&sl, 3);//SLPushBack(&sl, 4);//SLPrint(&sl);头插//SLPushFront(&sl, 5);//SLPushFront(&sl, 6);//SLPushFront(&sl, 7);//SLPushFront(&sl, 8);//SLPrint(&sl);//尾删//SLPopBack(&sl);//SLPrint(&sl);//SLPopBack(&sl);//SLPrint(&sl);头删//SLPopFront(&sl);//SLPrint(&sl);//SLPopFront(&sl);//SLPrint(&sl);//任意位置插入删除/*SLInsert(&sl, 0, 9);SLPrint(&sl);SLErase(&sl, 8);SLPrint(&sl);bool ret = SLFind(&sl, 9);if (ret)printf("找到了\n");elseprintf("没找到\n");SLDestroy(&sl);*/
//}
void Contact01()
{contact con;ContactInit(&con);//往通讯录中插入数据ContactAdd(&con);ContactAdd(&con);ContactShow(&con);//从通讯录里删除指定的数据ContactDel(&con);ContactShow(&con);//从通讯录里查找指定的联系人ContactFind(&con);//在通讯录里修改指定的联系人ContactModify(&con);ContactDestroy(&con);}
void menu()
{printf("***************通讯录****************\n");printf("***** 1.添加联系人  2.删除联系人*****\n");printf("***** 3.修改联系人  4.查找联系人*****\n");printf("***** 5.查看通讯录  0.退出通讯录*****\n");printf("*************************************\n");}
int main()
{//SLtest();//Contact01();int op = -1;contact con;ContactInit(&con);do{menu();printf("请选择你要进行的操作:\n");scanf("%d", &op);switch (op){case 1:ContactAdd(&con);break;case 2:ContactDel(&con);break;case 3:ContactModify(&con);break;case 4:ContactFind(&con);break;case 5:ContactShow(&con);break;case 0:printf("已退出通讯录\n");break;default:printf("系统里没有找到你需要进行的操作,请重新输入:\n");break;}} while (op != 0);ContactDestroy(&con);return 0;
}

2.通讯录上层代码实现(通讯录结构)

(1).思路展示

1)由于,通讯录是基于动态顺序表实现的。
2)所以,通讯录上层代码,只需要在上上层代码的头文件代码中创建一个保存联系人的结构,然后再定义通讯录功能函数即可。
3)接着在通讯录上层代码的源文件中将这些功能函数实现即可。
4)基于前面,我们已经知道,通讯录是基于动态顺序表实现的,所以在实现通讯录功能函数时,只需要在通讯录上层代码的源文件中,加上顺序表的头文件就可以调运顺序表的函数来实现通讯录了。

(2).上层代码实现(通讯录)

1.

Contact.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1//创建保存联系人的结构
#define NAME_MAX 100
#define SEX_MAX 10
#define TEL_MAX 15
#define ADDR_MAX 100struct ContactInfo
{char name[NAME_MAX];//名字char sex[SEX_MAX];//性别int age;//年龄char tel[TEL_MAX];//电话char addr[ADDR_MAX];//家庭住址
};
typedef struct ContactInfo CInfo;//通讯录底层是用顺序表来实现的
typedef struct SeqList contact;//通讯录的初始化和销毁
void ContactInit(contact* pcon);
void ContactDestroy(contact* pcon);//添加联系人
void ContactAdd(contact* pcon);
//删除联系人
void ContactDel(contact* pcon);
//修改联系人
void ContactModify(contact* pcon);
//查看通讯录
void ContactShow(contact* pcon);
//查找联系人
void ContactFind(contact* pcon);

2.

Contact.c
#include"Contact.h"
#include"SeqList.h"//通讯录的初始化与销毁
void ContactInit(contact* pcon)
{SLInit(pcon);
}void ContactDestroy(contact* pcon)
{SLDestroy(pcon);
}//添加联系人
void ContactAdd(contact* pcon)
{//接下来获取的都是结构体CInfo结构体里要求的数据CInfo 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);//联系人数据都获取到了,并保存到了结构体info中//往通讯录(顺序表)中插入数据SLPushBack(pcon, info);
}int FindByName(contact* pcon, char name[])
{for (int i = 0; i < pcon->size; i++){if (strcmp(pcon->a[i].name, name) == 0){return i;}}return -1;
}//删除联系人
void ContactDel(contact* pcon)
{//直接强制用户使用名称来查找printf("请输入要删除的联系人姓名:\n");char name[NAME_MAX];scanf("%s", name);int findidex = FindByName(pcon, name);if (findidex < 0){printf("要删除的联系人不存在!\n");return;}//找到了,要删除findidex位置的数据SLErase(pcon, findidex);printf("删除成功\n");
}//修改联系人选项
void MondifyMenu()
{printf("***************修改联系人选项****************\n");printf("***** 1.修改联系人名字  2.修改联系人性别*****\n");printf("***** 3.修改联系人年龄  4.修改联系人电话*****\n");printf("***** 5.修改联系人住址  0.退出删除选项*******\n");printf("******************************************\n");
}
//修改联系人
void ContactModify(contact* pcon)
{printf("请输入你需要修改的联系人:\n");char name[NAME_MAX];scanf("%s", name);int find = FindByName(pcon, name);if (find < 0){printf("要修改的联系人不存在!\n");return;}printf("找到了:\n");printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%-5s %-5s %-4d %-4s %-4s\n",pcon->a[find].name,pcon->a[find].sex,pcon->a[find].age,pcon->a[find].tel,pcon->a[find].addr);int val = -1;do{MondifyMenu();printf("请选择你需要修改的信息:\n");scanf("%d", &val);switch (val){case 1:printf("请输入修改后的联系人姓名:\n");scanf("%s", pcon->a[find].name);break;case 2:printf("请输入修改后的联系人性别:\n");scanf("%s", pcon->a[find].sex);break;case 3:printf("请输入修改后的联系人年龄:\n");scanf("%d", &pcon->a[find].age);break;case 4:printf("请输入修改后的联系人电话:\n");scanf("%s", pcon->a[find].tel);break;case 5:printf("请输入修改后的联系人住址:\n");scanf("%s", pcon->a[find].addr);break;case 0:printf("修改成功\n");printf("已退出删除联系人选项\n");break;default:printf("没有找到要修改的选项 请重新选择:\n");break;}} while (val != 0);}
//查看通讯录
void ContactShow(contact* pcon)
{//打印表头printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");for (int i = 0; i < pcon->size; i++){printf("%-5s %-5s %-4d %-4s %-4s\n", pcon->a[i].name,pcon->a[i].sex,pcon->a[i].age,pcon->a[i].tel,pcon->a[i].addr);}}
//查找指定联系人
void ContactFind(contact* pcon)
{printf("请输入你要查找的联系人:\n");char name[NAME_MAX];scanf("%s", name);int findidex = FindByName(pcon, name);if (findidex < 0){printf("你要查找的联系人不存在!\n");return;}printf("找到了:\n");printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%-5s %-5s %-4d %-4s %-4s\n",pcon->a[findidex].name,pcon->a[findidex].sex,pcon->a[findidex].age,pcon->a[findidex].tel,pcon->a[findidex].addr);
}

3.通讯录代码运行展示(数据只用于测试,无实际意义)

(1)测试展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)升华总结

这里只是展示基于动态顺序表实现通讯录的大致框架,和一些基本功能,有兴趣,能力的小伙伴,也可以下去拓展一下通讯录的其他功能,优化的更加完善,美观的通讯录。
感谢学习!

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

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

相关文章

idea中导入eclipse的javaweb项目——tomact服务(保姆级别)

idea中导入eclipse的javaweb项目——tomact服务&#xff08;保姆级别&#xff09; 1. 导入项目2. Project Settings下的各种配置步骤2.1 检查/修改 jdk 的引入2.2 配置Modules-Dependencies2.2.1 删掉eclipse相关的多余配置2.2.2 删掉jar包2.2.3 添加tomcat的依赖 2.3 配置Libr…

基于单目的光流法测速

目录 1.简介 2.代码实现 1.简介 基于单目的光流法是一种常见的计算机视觉技术&#xff0c;用于估计图像序列中物体的运动速度。它通过分析连续帧之间的像素变化来推断物体在图像中的移动情况。 背景&#xff1a; 光流法是计算机视觉领域中最早的运动估计方法之一&#xff0c…

HTML图片标签(2) HTML5+CSS3+移动web 前端开发入门笔记(三)

图片标签 HTML中&#xff0c;可以使用标签来插入图片。具体的语法为&#xff1a; <img src"图片路径" alt"替代文本">其中&#xff0c;src属性用于指定图片的路径&#xff0c;可以是相对路径或绝对路径。常见的有相对当前HTML文件的路径&#xff0…

【灵动 Mini-G0001开发板】+Keil5开发环境搭建+ST-Link/V2程序下载和仿真+4颗LED100ms闪烁。

我们拿到手里的是【灵动 Mini-G0001开发板】 如下图 我们去官网下载开发板对应资料MM32G0001官网 我们需要下载Mini—G0001开发板的库函数与例程&#xff08;第一手学习资料&#xff09;Keil支持包&#xff0c; PCB文件有需要的&#xff0c;可以自行下载。用户指南需要下载&a…

k8s 1.28版本二进制安装

本文目录 二进制安装Kubernetes&#xff08;k8s&#xff09;v1.28.0介绍1.环境1.0.环境准备1.Linux网卡没有eth0显示ens33或者其它&#xff08;以ens33为例&#xff09;方法一&#xff1a;修改网卡配置方法二&#xff1a;重新安装机器(本文为虚拟机) 2.克隆的虚拟机&#xff0c…

机器人控制算法——两轮差速驱动运动模型

1.Introduction 本文主要介绍针对于两轮差速模型的逆运动学数学推导。因为在机器人控制领域&#xff0c;决策规划控制层给执行器输出的控制指令v(车辆前进速度)和w(角速度)&#xff0c;因此&#xff0c;我们比较关心&#xff0c;当底层两个驱动电机接收到此信息&#xff0c;如何…

进化算法------代码示例

目录 前言代码示例1、寻找函数最大值2、句子匹配 前言 遗传算法就是在一个解空间上&#xff0c;随机的给定一组解&#xff0c;这组解称为父亲种群&#xff0c;通过这组解的交叉&#xff0c;变异&#xff0c;构建出新的解&#xff0c;称为下一代种群&#xff0c;然后在目前已有…

集成内部高端电源开关LTC3637HMSE、LTC3637MPMSE稳压器,TJA1443AT汽车CAN FD收发器。

一、LTC3637 76V、1A 降压型稳压器 &#xff08;简介&#xff09;LTC3637是一款高效率降压DC/DC稳压器&#xff0c;集成内部高端电源开关&#xff0c;功耗仅12μA DC&#xff0c;空载时可保持稳定的输出电压。LTC3637可提供高达1A的负载电流&#xff0c;并具有可编程峰值电流限…

【Redis】Java客户端使用zset命令

zadd/zrange zcard zrem zscore zrank

毅速丨模具3D打印材料有哪些选择

当前1.2709和CX是市面上最常用的3D打印模具钢材料&#xff0c;模具3D打印有没有更多的材料选择呢&#xff1f; 据了解&#xff0c;上海毅速推出的几款3D打印新材料正在被越来越多的行业所采用。如毅速的EM191S高性能高抛光不锈钢粉末&#xff0c;这款材料的抗开裂和耐腐蚀性能是…

Python学习基础笔记七十——模块和库1

模块和库&#xff1a; 一个python代码文件就实现了功能。功能比较单一。 在企业中&#xff0c;项目开发的文件&#xff0c;可能有成百上千个。 不同的代码文件&#xff0c;实现了不同的功能模块&#xff0c;就像一块块积木一样。这些功能文件整合起来&#xff0c;实现一个完…

javascript将html中的dom元素转图片

javascript将html中的dom元素转图片 百度网盘下载html2canvas.min.js&#xff1a; 全部文件-》js插件-》 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>网页中的某个区域转图片</title></head><body styl…

Django 使用Mysql数据库

目录 Django 使用Mysql数据库本地安装Mysql数据服务安装好Pymysql服务Django配置数据库迁移各种报错无法找到mysqlclient数据库拒绝连接 Django 使用Mysql数据库 本地安装Mysql数据服务 安装好Pymysql服务 python3 -m pip install PyMySQL官方文档介绍 Django配置 官网文档 …

Ubuntu中不能使用ifconfig命令

​ 问题 打开终端使用如下命令不能运行&#xff1a; ifconfig显示如下错误: 解决方法 在VMware中的虚拟机下面打开“编辑虚拟机设置”&#xff0c;或者在已经打开的虚拟机面板上面打开“虚拟机—设置” 选择网络适配器&#xff0c;选择“NAT模式”&#xff0c;没开机的就…

微软10月补丁 | 修复103个漏洞,包括2个零日漏洞,13个严重漏洞

近日&#xff0c;微软发布了2023年10月的补丁更新&#xff0c;解决了其软件中的103个漏洞。 在这103个漏洞中&#xff0c;有13个的评级为严重漏洞&#xff0c;90个被评为重要漏洞。自9月12日以来&#xff0c;谷歌已经解决了基于chrome的Edge浏览器的18个安全漏洞。 这两个零日…

第一个C++程序

1.include指令 也称包含指令&#xff0c;可根据文件名将文件内容包含进来。包含文件类型有.h头文件、.c, .cpp ,.txt等编译器能识别的代码文件。 2.头文件 C程序头文件是以.h为后缀&#xff0c;但在文件包含时规定要去掉.h后缀&#xff0c;放入std名字空间中 若头文件是C也有…

在不安全的集群上启用 Elasticsearch Xpack 安全性

本博文详细描述如何把一个没有启动安全的 Elasticsearch 集群升级为一个带有 HTTPS 访问的启用 Elasticsearch xpack 安全的集群。 为了增强 Elasticsearch 集群的安全性&#xff0c;你需要执行完全集群重启&#xff0c;并在客户端进行一些更改。 启用身份验证后&#xff0c;所…

YOLOv5算法改进(19)— Neck网络介绍(AFPN和BiFPN)

前言:Hello大家好,我是小哥谈。Neck网络是目标检测中的一个重要组成部分,主要用于对检测器提取的特征进行进一步处理和融合,以提高检测精度。通常,Neck网络由一系列卷积层、池化层、上采样层等组成,可以将不同层次的特征进行融合,同时也可以对特征进行降维和升维操作。本…

【Rust】包和模块,文档注释,Rust格式化输出

文章目录 包和模块包 CrateRust 的标准目录结构 模块 Module用路径引用模块使用super引用模块使用self引用模块结构体和枚举的可见性 使用 use 引入模块及受限可见性基本引入方式绝对路径引入模块相对路径引入模块中的函数 避免同名引用 注释和文档文档注释包和模块级别的注释注…

【Java学习之道】线程的创建与启动

引言 如果你正在学习Java编程&#xff0c;那么你可能已经知道Java是一种多线程编程语言。多线程编程可以帮助我们更高效地利用CPU&#xff0c;同时完成多项任务。但是&#xff0c;你可能还不知道如何在Java中创建和启动线程。在本节中&#xff0c;我们将深入探讨Java中的线程创…