探索C语言数据结构:利用顺序表完成通讯录的实现

在好久之前我就已经学习过顺序表,但是在前几天再次温习顺序表的时候,我惊奇的发现顺序编表可以完成我们日常使用的通讯录的功能,那么今天就来好好通过博客总结一下通讯录如何完成吧。

常常会回顾努力的自己,所以要给自己的努力留下足迹。

为今天努力的自己打个卡,留个痕迹吧

                                                                                                        2024.04.20     小闭


顺序表

顺序表在好久之前就已经写过一篇博客了,如果没了解过顺序表的佬,可以先去了解一下唔。传送门:http://t.csdnimg.cn/DhcZ7icon-default.png?t=N7T8http://t.csdnimg.cn/DhcZ7

了解过顺序表的就可以跟着往下看看如何使用顺序表来实现通讯录,下面先给大家展示一下顺表的C语言代码,不然等下就对通讯录的一些知识点给搞迷糊了。

顺序表是我们对数据进行管理的一种简单结构,他的底层就是数组,这里我们对数组进行封装就形成了我们的通讯录。

顺序表的头文件 "SL.h"

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"typedef struct Contact Datetype;struct SEQlist
{Datetype*  a;int size;int capacity;};typedef struct SEQlist SL;
void Init(SL* s);
void Print(SL* s);
void pushFront(SL* s, Datetype x);void INti(SL* s);
void tCheckCapacity(SL* s);
void SeqListPushBack(SL* s, Datetype x);
void SeqListPopBack(SL* s);
void SeqListPushFront(SL* s, Datetype x);
void SeqListPopFront(SL s);
void SeqListDestory(SL* s);
void SeqListinsert(SL* s, int pos,Datetype x);
void SeqListdel(SL* s, int pos);

顺序表的“.c”文件SL.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include "SL.h"//void Print(SL* s)
//{
//	for (int i = 0; i < s->size; i++)
//	{
//		printf("%d ", s->a[i]);
//	}
//	printf("\n");
//}void Init(SL* s)
{s->a = NULL;s->size = 0;         // 表示数组中存储了多少个数据s->capacity = 0;   数组实际能存数据的空间容量是多大 }void CheckCapacity(SL* s)
{// 如果没有空间或者空间不足,那么我们就扩容if (s->size == s->capacity){int newcapacity = s->capacity == 0 ? 4 : s->capacity * 2;Datetype* tmp = (Datetype*)realloc(s->a, newcapacity * sizeof(Datetype));if (tmp == NULL){printf("realloc 失败\n");exit(-1);}s->a = tmp;s->capacity = newcapacity;}
}void SeqListPushBack(SL* s, Datetype x)
{CheckCapacity(s);s->a[s->size] = x;s->size++;
}void SeqListPopBack(SL* s)
{// 暴力处理方式assert(s->size > 0);s->size--;
}void SeqListPushFront(SL* s, Datetype x)
{CheckCapacity(s);// 挪动数据int end = s->size - 1;while (end >= 0){s->a[end + 1] = s->a[end];--end;}s->a[0] = x;s->size++;
}void SeqListPopFront(SL* s)
{assert(s->size > 0);// 挪动数据int begin = 1;while (begin < s->size){s->a[begin - 1] = s->a[begin];++begin;}s->size--;
}void SeqListDestory(SL* s)
{free(s->a);s->a = NULL;s->capacity = s->size = 0;
}void SeqListinsert(SL* s,int pos, Datetype x)
{assert(s);assert(pos >= 0 && pos<=s->size);CheckCapacity(s);for (int i = s->size; i > pos; i--){s->a[i] = s->a[i - 1];}s->a[pos] = x;s->size++;}void SeqListdel(SL* s, int pos)
{assert(s);assert(pos >= 0 && pos < s->size);for (int i = pos; i < s->size-1; i++){s->a[i] = s->a[i + 1];}s->size--;}

 上面的两段代码包含了顺序表的,格式化,销毁,头插,尾插,头删,尾删,指定位置插入。


通讯录的实现

首先我们要知道通讯录里有什么?我们当然知道里面有联系人的姓名,性别,年龄,电话,地址。

我们假设这个通讯录就储存这么些信息,那我们这些信息是不是我们所说的数据,前面我们往顺序表里储存的是整形数据那么现在我们数据类型改为这些信息不就好了,可能有人就会想这些信息有那么多,那我们的数据变量要一个一个建立出来吗?当然不是,代码要求的是简便,既然这些信息可能是不同数据类型,而且还不少,那么我们就可以用一个自定义类型-----结构体来作为数据类型的变量,然后结构体内部就可以储存这些信息,这样一来就简单多了。如下图所示:


有了大概的思路,然后就开始封装顺序表,然后就让它成为一个成熟的通讯录。

创建通讯录的信息结构体和通讯录节点

具体思路:首先我们在建立两个文件一个“Contact.c”,“Contact.h”文件,其中在“Contact.h”文件里定义好储存联系人信息的结构体和声明函数和头文件,

“Contact.h”

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MAX_NAME 18
#define MAX_TEL 18
#define MAX_GENDER  10
#define MAX_ADDR 100typedef struct Contact
{char name[MAX_NAME];char gender[MAX_GENDER];int age;char tel[MAX_TEL];char addr[MAX_ADDR];}con;typedef struct SEQlist Ct;//通讯录的初始化
void ContactInit(Ct* pf);//通讯录的销毁
void ContactDestory(Ct* pf);//通讯录数据的添加
void ContactAdd(Ct* pf);//通讯录数据的删除
void ContactDel(Ct* pf,char arr[]);//通讯录的展示
void ContactShow(Ct* pf);//通讯录的查找
void ContactFind(Ct* pf,char arr[]);

 这里我们加了一个typedef struct SEQLIST Ct;是为了让人一眼看出这是通讯录而不是一个普通的顺序表,也让我们能够好理解一些。

以及在“Contact.c”文件里写下完成通讯录的一些基本功能的代码。

那么我们可以写的通讯录功能有哪些呢?

通讯录的格式化

void ContactInit(Ct* pf)
{Init(pf);}
void Init(SL* s)
{s->a = NULL;s->size = 0;         // 表示数组中存储了多少个数据s->capacity = 0;   数组实际能存数据的空间容量是多大 }

 

其实这里的格式化就是将顺序表给格式化,会先将结构体数组a给赋为NULL,然后将容量

(int capacity)和有效数据数目(int size)置为0 

通讯录的销毁

void ContactDestory(Ct* pf)
{SeqListDestory(pf);}
void SeqListDestory(SL* s)
{free(s->a);s->a = NULL;s->capacity = s->size = 0;
}

 通讯录的销毁也是一样的,直接调用链表的销毁就好了

通讯录数据的添加

void ContactAdd(Ct* pf)
{assert(pf);struct Contact a;printf("请输入你要添加联系人的姓名\n");scanf("%s", a.name);printf("请输入你要添加联系人的性别\n");scanf("%s", a.gender);printf("请输入你要添加联系人的年龄\n");scanf("%d", &(a.age));printf("请输入你要添加联系人的电话\n");scanf("%s", a.tel);printf("请输入你要添加联系人的地址\n");scanf("%s", a.addr);//往联系人里添加数据SeqListPushBack(pf, a);}
void SeqListPushBack(SL* s, Datetype x)
{CheckCapacity(s);s->a[s->size] = x;s->size++;
}

 因为要添加数据,那我们首先就需要获取这个数据,这里我们运用scanf来进行获取数据放到我们用来储存数据的结构体(struct Contact)中,然后再运用链表的尾插功能,将数据添加到我们的顺序表中。

通讯录数据的删除

我们要删除通讯录里的联系人,首先就得核对通讯录里是否有我们操作者想要删除的人,所以这里我们在写一个函数来进行找人,如果找到此人则返回此人在数组a的下标。,没有则打印“未找到该联系人”,并返回-1;然后在ContactDel中进行一下判断是否为-1,如果不为-1,就执行链表中的指定位置删除

//找到某位联系人的位置
int Findname(Ct* pf,char arr[])
{assert(pf);int i = 0;for (i = 0; i < pf->size; i++){if (strcmp(arr, pf->a[i].name) == 0){return i;}}printf("未找到该联系人\n");}
//删除联系人
void ContactDel(Ct* pf)
{assert(pf);int arr[MAX_NAME];scanf("%s", arr);printf("请输入你要删除的联系人: ");int find=Findname(pf,arr);if (find != -1){SeqListdel(pf, find);}}

 

void SeqListdel(SL* s, int pos)
{assert(s);assert(pos >= 0 && pos < s->size);for (int i = pos; i < s->size-1; i++){s->a[i] = s->a[i + 1];}s->size--;}

 

通讯录的查找

这里我们scanf输入想要查找的联系人,调用查找函数返回得到该联系人的下标,之后再打印出来即可。

//找到某位联系人的位置
int Findname(Ct* pf,char arr[])
{assert(pf);int i = 0;for (i = 0; i < pf->size; i++){if (strcmp(arr, pf->a[i].name) == 0){return i;}}printf("未找到该联系人\n");}
void ContactFind(Ct* pf)
{assert(pf);char arr[MAX_NAME];printf("请输入你要查找的联系人: ");scanf("%s", arr);int find=Findname(pf,arr);if (find != -1){printf("找到该联系人了,其信息如下:\n");printf("姓名    性别     年龄     电话       地址\n");printf("%s      %s       %d        %s         %s",pf->a[find].name, pf->a[find].gender, pf->a[find].age, pf->a[find].tel, pf->a[find].addr);}

 

通讯录的展示

这里就是遍历顺序表,将每个数据给打印出来,只要注意打印格式即可,想要美观可以调好打印的距离。


//通讯录的展示
void ContactShow(Ct* pf)
{assert(pf);int i = 0;for (i = 0; i < (pf->size); i++){printf("姓名    性别     年龄     电话       地址\n");printf("%s      %s       %d        %s         %s\n",pf->a[i].name, pf->a[i].gender, pf->a[i].age, pf->a[i].tel, pf->a[i].addr);}}


可能有人会问,我储存的数据程序一结束,数据就不见了,这还叫通讯录吗?这样确实显得这个通讯录有点鸡肋,所以我们现在就可以再写一个函数,将数据放到文本文件中进行储存

void SaveContact(Ct* 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->a + i, sizeof(PeoInfo), 1, pf);}printf("通讯录数据保存成功!\n");
}

当然这里是以二进制文件储存的。 

这些功能都是在“Contact.c”里来完成的。


常常会回顾努力的自己,所以要给自己的努力留下足迹。

为今天努力的自己打个卡,留个痕迹吧

                                                                                                        2024.04.20     小闭
 

                          

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

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

相关文章

OpenHarmony其他工具类—lua

简介 Lua是一种功能强大、高效、轻量级、可嵌入的脚本语言。 支持过程编程、面向对象编程、函数编程、数据驱动编程和数据描述。 下载安装 直接在OpenHarmony-SIG仓中搜索lua并下载。 使用说明 以OpenHarmony 3.1 Beta的rk3568版本为例 将下载的lua库代码存在以下路径&#…

Java Web3-2 - tomcat

https://github.com/heibaiying/Full-Stack-Notes/blob/master/notes/Tomcat_架构解析.md https://zhuanlan.zhihu.com/p/40249834 早期&#xff0c;web技术主要用于浏览静态页面 时间发展&#xff0c;用户已经不满足于仅浏览静态页面。用户需要一些交互操作&#xff0c;获取…

STM32G431RBT6之时钟树配置与生成工程

默认大家都下载了蓝桥杯嵌入式资源包了哈. 首先,打开cubumx,修改RCC与SYS. 打开并观察原理图,发现晶振是24Mhz. 第一步,打开Clock Configuration. 第二步,修改晶振为原理图相对应的24Mhz. 第三步,切换到HSE. 第四步,切换到PLLCLK. 第五步,设置HCLK为80Mhz(15届真题要求为8…

洛谷P1057 [NOIP2008 普及组] 传球游戏

#include<iostream> using namespace std; int n;// n个人传球游戏 默认开始球在编号为1的位置 int m;// 传递m次球 int main(){cin>>n>>m;// 动态转方程&#xff1a;// 球传递到编号为k人的手中// 种类总数 传递到k-1编号种类总数 传递到k1编号种类总数//…

wsl2 Ubuntu子系统内存只有一半的解决办法

物理机的内存是64G&#xff0c;在wsl2安装完Ubuntu20.04后&#xff0c;输入命令&#xff1a; free -g 发现只有32G&#xff0c;原因是默认只能获得物理机一半的内存&#xff1a; WSL 中的高级设置配置 | Microsoft Learn 因此可手动修改为与物理机同等大小&#xff1a; 1&a…

再拓信创版图-Smartbi Insight V11与东方国信CirroData数据库完成兼容适配认证

近日&#xff0c;思迈特商业智能与数据分析软件 [简称&#xff1a;Smartbi Insight] V11与北京东方国信科技股份有限公司 &#xff08;以下简称东方国信&#xff09;CirroData-OLAP分布式数据库V2.14.1完成兼容性测试。经双方严格测试&#xff0c;两款产品能够达到通用兼容性要…

Cronjob提权

参考&#xff1a; https://redpomelo.xyz/archives/1699953656909 前言 提权为该靶机的精髓&#xff0c;Cronjob通常以root特权运行。如果我们可以成功篡改cronjob中 定义的任何脚本或二进制文件&#xff0c;那么我们可以以root特权执行任意 代码。 什么是Cronjob&#xf…

Jmeter 性能-死锁问题定位+分析

1、环境搭建 ①准备脚本&#xff0c;执行压测 ②用Jstack 打印日志 jstack 112759 >dead.log ③下载日志到本地 sz dead.log 2、问题定位 ①打开dead.log&#xff0c;搜索deadlock ②查看死锁的线程 ③查看死锁位置 3、问题分析 ①下载死锁的类文件 Sz CaseControlle…

使用iMazing对iPhone有影响吗 为什么iPhone都会装iMazing来管理 苹果手机imazing安装

随着科技的迅速发展&#xff0c;智能手机已成为我们日常生活中不可或缺的一部分&#xff0c;iPhone手机占据了智能手机市场的大部分&#xff0c;也有着庞大的用户基础。随着时代的发展&#xff0c;用户对于更高级的设备管理工具的需求也随之增加。iMazing作为一款强大的设备管理…

美业连锁门店收银系统源码-如何查看收款门店对应的加盟商?

美业管理系统源码 博弈美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 促销活动 PC管理后台、手机APP、iPad APP、微信小程序 第一步&#xff1a; 登录pc管理后端 第二步&#xff1a; 进入企业组织管理-门店管理&a…

pandas/python 一个实战小案例

上次写坦克游戏的时候&#xff0c;接触了一点pandas&#xff0c;当时只是简单了解了一下如何遍历行和列并获取值来替换图片&#xff0c;想更多了解pandas。正好有一些数据需要筛选&#xff0c;试试能不能用通过代码实现。虽然总的来说不复杂&#xff0c;但由于原始数据在命名、…

ai写作强大,ai写作哪个软件最好用?

在当今数字化时代&#xff0c;ai技术的发展正以惊人的速度改变着我们的生活和工作方式。其中&#xff0c;ai写作作为一项令人瞩目的创新&#xff0c;展示了强大的文本生成能力。然而&#xff0c;随着各种ai写作软件的涌现&#xff0c;人们不禁困惑&#xff1a;哪个软件才是最好…

SQLite数据库中JSON 函数和运算符(二十七)

返回&#xff1a;SQLite—系列文章目录 上一篇:维护SQLite的私有分支&#xff08;二十六&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 ​1. 概述 默认情况下&#xff0c;SQLite 支持 29 个函数和 2 个运算符 处理 JSON 值。还有两个表值函数可用于分解 JSON 字…

大模型应用开发基础

AGI 时代&#xff0c;AI 无处不在&#xff0c;形成新的社会分层&#xff1a; AI 使用者&#xff0c;使用别人开发的 AI 产品AI 产品开发者&#xff0c;设计和开发 AI 产品基础模型相关&#xff0c;训练基础大模型&#xff0c;或为大模型提供基础设施 越向下层&#xff0c;重要…

MEMENTO(备忘录)-- 对象行为型模式

意图&#xff1a; 在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 别名&#xff1a; Token 动机&#xff1a; 有时必要记录一个对象的内部状态。 适用性&#xff1a; a. 必…

【云计算】云数据中心网络(五):对等连接

《云网络》系列&#xff0c;共包含以下文章&#xff1a; 云网络是未来的网络基础设施云网络产品体系概述云数据中心网络&#xff08;一&#xff09;&#xff1a;VPC云数据中心网络&#xff08;二&#xff09;&#xff1a;弹性公网 IP云数据中心网络&#xff08;三&#xff09;…

跟TED演讲学英文:How AI could save (not destroy) education by Sal Khan

How AI could save (not destroy) education Link: How AI could save (not destroy) education Speaker: Sal Khan Date: April 2023 文章目录 How AI could save (not destroy) educationIntroductionVocabularyTranscriptSummary后记 Introduction Sal Khan, the founder…

遥瞻智慧:排水系统远程监控的卓越解决方案

遥瞻智慧&#xff1a;排水系统远程监控的卓越解决方案 在城市脉络的深层肌理中&#xff0c;排水系统犹如一条条隐秘的生命线&#xff0c;默默承载着城市的呼吸与律动。然而&#xff0c;如何以科技之眼&#xff0c;赋予这些无形网络以实时感知、精准调控的能力&#xff0c;使之…

网络管理实验三、SNMP协议工作原理验证与分析

1 实验概括 实验目的&#xff1a; 学习捕获SNMP报文&#xff0c;通过报文分析理解SNMP协议的工作过程。 实验内容&#xff1a; 1&#xff09; 使用snmputilg发送SNMP数据包; 使用wireshark抓包&#xff1b;使用netstat –an查看代理站TCP/UDP连接表&#xff1b; 2&#xff09;…

识周期以备,用周期以对

坐在阳台上喝茶&#xff0c;看着三角梅的花朵绽放着&#xff0c;凋零着&#xff0c;随风飘落… 春夏秋冬&#xff0c;花开花落。不禁感慨生命之渺小&#xff0c;敬畏周期的力量。 今天抽空聊聊周期&#xff0c;周期的核心是均值回归&#xff0c;周期也是“道”。 1 过去40年&am…