基于顺序表实现通讯录项目

目录

1.通讯录的基本构成

2.通讯录的底层原理

3.通讯录的底层——顺序表

———————————————————————————————————————————

正文开始

1. 通讯录的基本构成

1.1 联系人信息的主要内容

        ●姓名

        ●性别

        ●年龄

        ●电话

        ●住址

1.2 数据结构选择顺序表的原因

        ●顺序存储的优点,如可以直接通过下标快速访问元素,存储密度高。

        ●对于通讯录这种数据规模相对较小且操作相对简单的应用,顺序表易于实现和理解。

2.通讯录的底层原理

2.1顺序表的概念和特点

  • 顺序表是一种线性表的数据结构,它将元素依次存储在连续的内存空间中。
  • 特点包括随机访问、存储密度高,但插入和删除操作可能需要移动大量元素。

通讯录是顺序表构成,顺序表的每个元素是一个自定义的结构体。

2.2基于顺序表实现通讯录的具体方法

  • 如何将联系人信息存储在顺序表中,例如可以定义一个结构体来表示联系人,然后用数组来实现顺序表。

一般在VS2022这个环境下,我们分文件实现项目。

SeqList.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;		//有效数据个数int capacity;	//空间容量
}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);
//顺序表的查找
int SLFind(SL* ps, SLDataType x);
  • 实现通讯录的基本操作,如添加联系人、删除联系人、查找联系人、修改联系人信息等。
     

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1#include "SeqList.h"//顺序表的初始化
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr){free(ps->arr);ps->arr = NULL;ps->size = ps->capacity = 0;}
}
//插入前先看空间够不够(从尾插复用)
void SLCheckCapacity(SL* ps)
{if (ps->capacity == ps->size){//申请空间int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//要申请多大的空间if (tmp == NULL){perror("realloc fail!");exit(1);//直接退出程序}//空间申请成功ps->arr = tmp;ps->capacity = newCapacity;}
}
//顺序表的尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//插入前先看空间够不够if (ps->capacity == ps->size){//申请空间int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//要申请多大的空间if (tmp == NULL){perror("realloc fail!");exit(1);//直接退出程序}//空间申请成功ps->arr = tmp;ps->capacity = newCapacity;}SLCheckCapacity(ps);//最后进行插入ps->arr[ps->size++] = x;
}
//打印函数
void SLPrint(SL ps)
{int i = 0;for (i = 0; i<ps.size; i ++){printf("%d ", ps.arr[i]);}printf("\n");
}
//顺序表的头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//先让顺序表中数据整体往后挪for (int i = ps->size; i>0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;//挪完插入ps->size++;
}
//顺序表的尾删
void SLPopBack(SL* ps)
{assert(ps);//先判断有没有数据给我们删assert(ps->size);--ps->size;
}
//顺序表的头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//数据整体往前挪动一位for (int i = 0; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >=0 && pos <= ps->size);//插入前先检查空间够不够SLCheckCapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}
//删除指定位置的数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
//顺序表的查找
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){//找到了return i;}}//没有找到return -1;
}

实现完每个方法后,我们不急于将这些底层代码用于实现项目,首先通过自己的测试,所以我们还得创建一个

test.c文件:用于测试方法用例

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLTest01()
{SL sl;SLInit(&sl);//顺序表的初始化SLPushBack(&sl,1);//顺序表的尾插SLPushBack(&sl,2);SLPushBack(&sl,3);SLPushBack(&sl,4);SLPrint(sl);//1 2 3 4SLPushFront(&sl, 99);//顺序表的头插SLPrint(sl);//99 1 2 3 4SLPopBack(&sl);//顺序表的尾删SLPrint(sl);//99 1 2 3SLPopFront(&sl);//顺序表的头删SLPrint(sl);//1 2 3SLInsert(&sl, 1, 3);//在指定位置之前插入数据SLPrint(sl);//1 3 2 3SLErase(&sl, 1);SLPrint(sl);//1 2 3SLFind(&sl, 3);//顺序表的查找int find = SLFind(&sl, 3);if (find < 0){printf("找不到\n");}else{printf("找到了!下标为:%d\n", find);}SLDestroy(&sl);//顺序表的销毁
}int main()
{SLTest01();return 0;
}

3.通讯录的底层——顺序表

上面的方法都已经实现,接下来我们可以运用我们实现的现成的方法写一个项目——通讯录

还是分文件操作

Contact.c:

#include"Contact.h"
#include"SeqList.h"//通讯录的初始化
void ContactInit(Contact* con)//sl
{//实际上要进行的是顺序表的初始化//顺序表的初始化已经实现好了SLInit(con);
}
//通讯录的销毁
void ContactDesTroy(Contact* con)
{SLDestroy(con);
}
//通讯录添加数据
void ContactAdd(Contact* con)
{//获取用户输入的内容:姓名+性别+年龄+电话+地址peoInfo 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);//往通讯录中添加联系人数据SLPushBack(con, info);
}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 ContactDel(Contact* con)
{//要删除的数据必须要存在,才能执行删除操作//查找char name[NAME_MAX];printf("请输入要删除的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要删除的联系人数据不存在!\n");return;}//要删除的联系人数据存在--->知道了要删除的联系人数据对应的下标SLErase(con, find);printf("删除成功!\n");
}
//展示通讯录数据
void ContactShow(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].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}
}
//通讯录的修改
void ContactModify(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].gender);printf("请输入新的年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入新的电话:\n");scanf("%s", con->arr[find].tel);printf("请输入新的住址:\n");scanf("%s", con->arr[find].addr);printf("修改成功!\n");
}
//通讯录查找
void ContactFind(Contact* con)
{//11char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("要查找的联系人数据不存在!\n");return;}// 姓名 性别 年龄 电话  地址// 11   11   11   11   11printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%3s %3s %3d %3s %3s\n", //手动调整一下格式con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);
}

Contact.h

#pragma once#define NAME_MAX 20
#define GENDER_MAX 10 
#define TEL_MAX 20
#define ADDR_MAX 100
//定义联系人数据 结构
//姓名 性别 年龄 电话 地址
typedef struct personInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}peoInfo;//要用到顺序表相关的方法,对通讯录的操作实际就是对顺序表进行操作
//给顺序表改个名字,叫做通讯录
typedef struct SeqList Contact; //sl
//通讯录相关的方法//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDesTroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

Test.c

#include "SeqList.h"void menu()
{printf("******************通讯录******************\n");printf("*******1.增加联系人   2.删除联系人********\n");printf("*******3.修改联系人   4.查找联系人********\n");printf("*******5.展示联系人   0.   退出  *********\n");printf("******************************************\n");
}int main()
{int op = -1;Contact con;ContactInit(&con);do {menu();printf("请选择您的操作:\n");scanf("%d", &op);//要根据对应的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;
}

———————————————————————————————————————————

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

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

相关文章

第33次CCF计算机软件能力认证-第4题十滴水

题干&#xff1a; 十滴水是一个非常经典的小游戏。 小 C C C 正在玩一个一维版本的十滴水游戏。 我们通过一个例子描述游戏的基本规则。 游戏在一个 1 c 1c 1c 的网格上进行&#xff0c;格子用整数 x ( 1 ≤ x ≤ c ) x(1≤x≤c) x(1≤x≤c) 编号&#xff0c;编号从左往…

【Flutter、H5、Web?前端个人总结】分享从业经历经验、自我规范准则,纯干货

前言 hi&#xff0c;正式接触web前端已经经过了两年的时间&#xff0c;从大学的java后端转型到web前端&#xff0c;再到后续转战Flutter&#xff0c;逐渐对前端有了一些心得体会&#xff0c;其实在当下前端的呈现形式一直在变化&#xff0c;无论你是用原生、还是web还是混编的…

初始项目托管到gitee教程,开箱即用

0.本地仓库与远程仓库关联&#xff08;需先在gitee创建仓库&#xff09; ①打开powershell生成ssh key ssh-keygen -t ed25519 -C "Gitee SSH Key"-t key 类型-C 注释 生成成功如下&#xff0c;并按下三次回车 ②查看公私钥文件 ls ~/.ssh/输出&#xff1a; id_…

怎么提取伴奏?5个人声分离方法一步搞定!

在进行音乐创作或混音等操作时&#xff0c;提取出音乐中的伴奏是一个常见的需求。伴奏是指音乐中除了主旋律和歌唱部分之外的音轨&#xff0c;通常包括鼓、贝斯、吉他等乐器的演奏&#xff0c;提取出伴奏可以让我们更方便地对音乐进行处理。 本文分享几个可以提取伴奏的方法&a…

el-table表头加红色星标

代码&#xff1a; <el-table-column prop"name" label"姓名" width"auto"><template #header><span style"color: red; margin-right: 4px">*</span><span>姓名</span></template></el…

Mysql—高可用集群MHA

1:什么是MHA&#xff1f; MHA&#xff08;Master High Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出现就是解决MySQL 单点的问题。 MySQL故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障切换操作。 MHA能在故障切…

22个无版权的4K高清视频素材网站,各种风格视频都有!

平时我也会做一些短视频和宣传片&#xff01; 所以&#xff0c;对找素材这回事不在话下&#xff0c;国内外也有不少高清无水印的视频素材网站&#xff0c;今天就分享一些高清剪辑必备的视频素材渠道&#xff0c;不少也是免费哒&#xff0c;平时需要找素材的同学千万不要错过啦…

Python中的数据可视化艺术:用Matplotlib和Seaborn讲故事

Python中的数据可视化艺术&#xff1a;用Matplotlib和Seaborn讲故事 数据可视化不仅仅是图表的绘制&#xff0c;更是通过视觉形式传达复杂信息的一种艺术。使用Python中的两个强大的库——Matplotlib和Seaborn&#xff0c;可以将数据转化为清晰、优美的图表&#xff0c;帮助我…

【Kubernetes】常见面试题汇总(五十六)

目录 123. pod 创建失败&#xff1f; 124. kube-flannel-ds-amd64-ndsf7 插件 pod 的 status 为 Init:0/1 &#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#x…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-05

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-04 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-04目录1. LLM-Augmented Symbolic Reinforcement Learning with Landmark-Based Task Decomposition摘要研究背景问题与挑战如何…

『网络游戏』下线数据清理【29】

修改服务端脚本&#xff1a;ServerSession.cs 修改服务端脚本&#xff1a;ServerRoot.cs 修改服务端脚本&#xff1a;CacheSvc.cs 修改服务端脚本&#xff1a;LoginSys.cs 运行服务器 运行客户端 - 连续登录账号 本章结束

VSCode的常用插件(持续更新)

点击左边工具栏的“扩展”&#xff0c;在搜索栏中查找对应插件&#xff0c;点击“安装”&#xff0c;安装完成后右边界面的插件会显示“卸载”按钮。 1、中文&#xff08;简体&#xff09;语言包 2、Auto Rename Tag 修改开始标签&#xff0c;结束标签也会随之自动变化。 3、O…

docker+mysql创建用户名密码_docker里面的mysql 更换密码

进入mysql容器 操作vi etc/mysql/my.cnf 默认是不安装vi编辑器的&#xff0c;下面安装vi 更新安装包 apt-get update 安装vim 执行这条语句 apt-get install vim 到修改docker容器里面的mysql数据库密码了 启动mysql容器 docker exec -it mysql /bin/bash 编辑配置文件 我这里是…

【C++】第五节:内存管理

1、C/C内存分布 看下面一段代码 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)malloc(s…

与C++内存管理和STL简介的爱恨情仇

本文 1.C/C内存分布2.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free总结 3.C内存管理方式new/delete操作内置类型new和delete操作自定义类型 4.operator new与operator delete函数&#xff08;重要点进行讲解&#xff09;5.new和delete的实现原理内置类型自定…

制造业DT数字化之生产制造业务建模

一、工厂建模为何物&#xff1f; 对制造业人员&#xff08;人&#xff09;、设备&#xff08;机&#xff09;、材料&#xff08;料&#xff09;、工艺流程&#xff08;法&#xff09;、工厂环境&#xff08;环&#xff09;数据化管理的过程就叫工厂建模。 二、制造建模有哪几大…

【操作系统】引导(Boot)电脑的奇妙开机过程

&#x1f339;&#x1f60a;&#x1f339;博客主页&#xff1a;【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见&#xff1a;【C语言专项】 目录 什么是操作系统的引导&#xff1f; 操作系统的引导&#xff08;开机过程&#xff09; Windows操作系…

QD1-P2 HTML 编辑器:HBuilderX

本节学习&#xff1a; HTML课程内容介绍HBuilderX编辑器的使用 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p2 HTML 内容 基础语法 标签整体架构DOCTYPE 常用标签 标题和水平线段落和换行列表div 和 span格式化标签图片超链接标签表格表单字符实体 编辑器 HBuilder…

设计测试用例的方法

目录 1、等价类 2、边界值 3、场景法 4、正交表法 5、设计正交表 6、判定表法 7、错误猜想法 1、等价类 在测试中选取一些数据作为等价类进行测试&#xff0c;如果测试通过&#xff0c;就代表测试通过&#xff0c;可以用少量代表性的测试数据取得较好的测试结果。 等价类…

智能扭矩系统在轨道交通行业的应用_SunTorque

【大家好&#xff0c;我是唐Sun&#xff0c;唐Sun的唐&#xff0c;唐Sun的Sun。一站式数智工厂解决方案服务商】 在现代轨道交通领域&#xff0c;安全、高效和可靠性是至关重要的考量因素。智能扭矩系统作为一项先进的技术&#xff0c;正逐渐在轨道交通行业中展现出其重要的应用…