C顺序表:通讯录

目录

前言

通讯录数据结构

通讯录初始化 

查找名字

增加联系人

删除联系人

展示所有联系人

查找联系人

修改信息

销毁通讯录

完整通讯录代码


前言

数据结构中的顺序表如果已经学会了,那么我们就可以基于顺序表来完成一个通讯录了

通讯录其实我们使用前面学习过的顺序表就能完成不过,相比较来说,前面的顺序表就是个整型数组,但通讯录就是一个多信息的自定义类型了

如果没了解过顺序表的可以看看我前篇博客

C数据结构:顺序表-CSDN博客

下面直接来开始完成我们的通讯录吧

通讯录数据结构

typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInfo;typedef PeoInfo SLDataType;
//typedef int SLDataType;typedef struct SeqList
{SLDataType* a;int size;     // 有效数据个数int capacity; // 空间容量
}SL;

通讯里结构体里定义了五个成员,名字、性别、年龄、电话、地址

数组大小使用了宏定义,因为有需要更改的时候就比较方便,不需要一个个去更改

下面就开始通讯录的实现吧

如果文件中有顺序表的.c文件,请务必屏蔽以下函数,否则会引起报错

 

 

1. SLPrint函数中含有 %d,%d是整型的占位符,如果我们需要打印自定义类型是不能使用%d占位符的

2. SLFind函数中if的判断条件 ps->a[i] == x这个有错误,我们的a数组的类型是个自定义类型,该类型里含有5个成员,怎么能直接让两个自定义类型直接比较呢?

通讯录初始化 

void InitContact(contact* con)
{SLInit(con);
}

初始化一个联系人就和初始化一个顺序表一样,所以直接使用顺序表的函数对里面的参数con进行初始化即可 

查找名字

int FindByName(contact* con, char name[])
{assert(con);for (int i = 0; i < con->size; i++){if (strcmp(con->a[i].name, name) == 0){return i;}}return -1;
}

为什么要先写查找名字呢?

因为我们后面删除联系人、查找联系人、修改联系人都会使用到这个模板,如果都按一个模板来写会显得代码很冗余,并且浪费时间,所以我们直接写一个函数就可以有效的解决这个问题

我们直接遍历整个联系人a数组里面的名字,当名字匹配的时候,我们就返回它的下标,否则出了循环之后说明没找到名字,则返回-1

我们不能直接写

con->a[i].name == name作为if语句的条件

因为这个name是个char类型的数组名,而数组名是地址,用地址来比较是得不出答案的,所以需要借助到string.h里的strcmp函数 

对string.h库函数有兴趣的可以看看我前面的博客 

ctype.h的了解string.h库函数中各个函数的使用和模拟实现-CSDN博客

增加联系人

void AddContact(contact* con)
{assert(con);PeoInfo c;printf("请输入姓名:>");scanf("%s", c.name);printf("请输入性别:>");scanf("%s", c.sex);printf("请输入年龄:>");scanf("%d", &c.age);printf("请输入电话:>");scanf("%s", c.tel);printf("请输入地址:>");scanf("%s", c.addr);SLPushBack(con, c);
}
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps); //检查数组大小是否足够ps->a[ps->size] = x;ps->size++;
}

 先是定义了一个通讯录c变量,并把我们需要增加的联系人的信息先暂时放到c中

最后使用顺序表里的SLPushBack函数将这些信息放到我们的通讯录数组中即可

删除联系人

void DelContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入要删除的姓名:>");scanf("%s", name);int pos = FindByName(con, name);if (pos < 0){printf("要删除的用户不存在!\n");return;}SLErase(con, pos);printf("删除成功\n");
}
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos <= ps->size && pos >= 0);assert(ps->size > 0);for (int i = pos; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

先定义了一个name数组接收我们要删除的人的名字,然后使用我们前面写到的FindByName找到这个名字的下标,最后使用SLErase函数删除掉通讯录数组这个下标所在的位置即可

展示所有联系人

void ShowContact(contact* con)
{assert(con);//打印表头printf("姓名\t性别\t年龄\t电话\t地址\n");for (int i = 0; i < con->size; i++){printf("%s\t%s\t%d\t%s\t%s\n", con->a[i].name,con->a[i].sex,con->a[i].age,con->a[i].tel,con->a[i].addr);}
}

展示这一步就是给使用者看的,为了美观对齐所以在每一个信息的后面加了一个\t

最后用for循环遍历通讯录数组打印所有的信息即可

查找联系人

void FindContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入要查找的姓名:>");scanf("%s", name);int pos = FindByName(con, name);if (pos < 0){printf("查找的用户不存在!\n");return;}printf("查找成功\n");printf("%s\t%s\t%d\t%s\t%s\t", con->a[pos].name,con->a[pos].sex,con->a[pos].age,con->a[pos].tel,con->a[pos].addr);
}

 还是一样先找到名字所在通讯录数组的下标,如果能找到说明联系人存在,利用下标打印出该人的信息即可

修改信息

void ModifyContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入要修改的姓名:>");scanf("%s", name);int pos = FindByName(con, name);if (pos < 0){printf("查找的用户不存在!\n");return;}printf("请输入姓名:>");scanf("%s", con->a[pos].name);printf("请输入性别:>");scanf("%s", con->a[pos].sex);printf("请输入年龄:>");scanf("%d", &con->a[pos].age);printf("请输入电话:>");scanf("%s", con->a[pos].tel);printf("请输入地址:>");scanf("%s", con->a[pos].addr);printf("修改成功\n");
}

也是一样先查找该名字所在通讯录数组的下标,然后重新使用scanf输入该下标的所有信息即可 

销毁通讯录

void DestroyContact(contact* con)
{assert(con);SLDestroy(con);
}
void SLDestroy(SL* ps)
{assert(ps);if (ps->a){free(ps->a);}ps->a = NULL;ps->capacity = ps->size = 0;
}

销毁直接用顺序表中的SLDestroy实现即可

完整通讯录代码

#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>#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);typedef PeoInfo SLDataType;
//typedef int SLDataType;// 动态顺序表 -- 按需申请
typedef struct SeqList
{SLDataType* a;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);void SLInit(SL* ps)
{assert(ps);ps->a = NULL;ps->capacity = ps->size = 0;
}void SLDestroy(SL* ps)
{assert(ps);if (ps->a){free(ps->a);}ps->a = NULL;ps->capacity = ps->size = 0;
}//void SLPrint(SL* ps)
//{
//	assert(ps);
//
//	for (int i = 0; i < ps->size; i++)
//	{
//		printf("%d ", ps->a[i]);
//	}
//	printf("\n");
//}void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->capacity == 0){ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);ps->capacity = 4;}if (ps->capacity == ps->size && ps->capacity != 0){//定义tmp接收防止扩容失败原数组被覆盖SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));if (tmp == NULL){perror("realloc fail!\n");return;}//扩容成功ps->a = tmp;ps->capacity *= 2;}
}void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}void SLPopBack(SL* ps)
{assert(ps);assert(ps->size > 0);ps->size--;
}void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size - 1; i >= 0; i--){ps->a[i + 1] = ps->a[i];}ps->a[0] = x;ps->size++;
}void SLPopFront(SL* ps)
{assert(ps);assert(ps->size > 0);for (int i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos <= ps->size && pos >= 0);SLCheckCapacity(ps);for (int i = ps->size; 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(pos <= ps->size && pos >= 0);assert(ps->size > 0);for (int i = pos; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}//int SLFind(SL* ps, SLDataType x)
//{
//	assert(ps);
//	
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->a[i] == x)
//		{
//			return i;
//		}
//	}
//
//	return -1;
//}void InitContact(contact* con)
{SLInit(con);
}void AddContact(contact* con)
{assert(con);PeoInfo c;printf("请输入姓名:>");scanf("%s", c.name);printf("请输入性别:>");scanf("%s", c.sex);printf("请输入年龄:>");scanf("%d", &c.age);printf("请输入电话:>");scanf("%s", c.tel);printf("请输入地址:>");scanf("%s", c.addr);SLPushBack(con, c);
}int FindByName(contact* con, char name[])
{assert(con);for (int i = 0; i < con->size; i++){if (strcmp(con->a[i].name, name) == 0){return i;}}return -1;
}void DelContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入要删除的姓名:>");scanf("%s", name);int pos = FindByName(con, name);if (pos < 0){printf("要删除的用户不存在!\n");return;}SLErase(con, pos);printf("删除成功\n");
}void ShowContact(contact* con)
{assert(con);//打印表头printf("姓名\t性别\t年龄\t电话\t地址\n");for (int i = 0; i < con->size; i++){printf("%s\t%s\t%d\t%s\t%s\n", con->a[i].name,con->a[i].sex,con->a[i].age,con->a[i].tel,con->a[i].addr);}
}void FindContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入要查找的姓名:>");scanf("%s", name);int pos = FindByName(con, name);if (pos < 0){printf("查找的用户不存在!\n");return;}printf("查找成功\n");printf("%s\t%s\t%d\t%s\t%s\t", con->a[pos].name,con->a[pos].sex,con->a[pos].age,con->a[pos].tel,con->a[pos].addr);
}void ModifyContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入要修改的姓名:>");scanf("%s", name);int pos = FindByName(con, name);if (pos < 0){printf("查找的用户不存在!\n");return;}printf("请输入姓名:>");scanf("%s", con->a[pos].name);printf("请输入性别:>");scanf("%s", con->a[pos].sex);printf("请输入年龄:>");scanf("%d", &con->a[pos].age);printf("请输入电话:>");scanf("%s", con->a[pos].tel);printf("请输入地址:>");scanf("%s", con->a[pos].addr);printf("修改成功\n");
}void DestroyContact(contact* con)
{assert(con);SLDestroy(con);
}void Test2()
{contact c;InitContact(&c);AddContact(&c);AddContact(&c);ShowContact(&c);//DelContact(&c);ModifyContact(&c);ShowContact(&c);FindContact(&c);DestroyContact(&c);
}int main()
{//Test1();Test2();return 0;
}

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

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

相关文章

Coding and Paper Letter(八十八)

系列重启之CPL。 1 Coding: 1.一个Python库用来分析城市路网的工具箱&#xff0c;城市形态分析工具。 Madina 2.SkyPilot&#xff1a;在任何云上运行 LLM、AI 和 Batch。 通过简单的界面即可实现最大程度的节省性能、最高的 GPU 可用性和托管执行。 skypilot 3.探索美国卫…

creo扫描杯子学习笔记

creo扫描杯子学习笔记 扫描2要素&#xff1a; 轨迹&#xff0c; 截面。 多用于曲线扫描&#xff0c;区别于拉伸命令。 大小自定 旋转扫描 抽壳 草绘把手 扫描把手 复制曲面 实例化切除 成型

08 | Swoole 源码分析之 Timer 定时器模块

原文首发链接&#xff1a;Swoole 源码分析之 Timer 定时器模块 大家好&#xff0c;我是码农先森。 引言 Swoole 中的毫秒精度的定时器。底层基于 epoll_wait 和 setitimer 实现&#xff0c;数据结构使用最小堆&#xff0c;可支持添加大量定时器。 在同步 IO 进程中使用 seti…

今年过去了多少天?(switch)

//今年已经过去了几天&#xff1f; #include <stdio.h> int monthday(int year,int month){switch(month){case 1:return 31;case 2:if ((year % 4 0 && year % 100 ! 0)||year % 400 0){return 29;}else{return 28;}break;case 3:return 31;case 4:return 30;…

C语言进阶课程学习记录-第24课 - #pragma 使用分析

C语言进阶课程学习记录-第24课 - #pragma 使用分析 #pragma实验-#pragma messagecmd窗口运行 实验-pragma oncebcc编译报错gcc编译成功global.h代码优化 #pragma pack实验BCC编译器输出 小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程…

k8s1(1),Linux运维基础开发与实践

#设置主机名 hostnamectl hostnameXXX #配置免密(包括操作机) ssh-keygen ssh-copy-id master*/slave* #传输hosts cat > /etc/hosts <<EOF 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain loca…

【Qt 学习笔记】Qt 中出现乱码的解释及讨论

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt 中出现乱码的解释及讨论 文章编号&#xff1a;Qt 学习笔记 / 06 文…

工单派单-saas工单处理软件效益分析,智能解决企业管理痛点亿发

企业对引入工单管理系统是有迫切需求的&#xff0c;工单管理系统可以有效地管理任务和工作流程&#xff0c;提高工作效率和客户满意度。 在没有工单管理系统之前&#xff0c;许多企业可能面临着诸如任务分配不清晰、信息不透明、工作流程混乱等管理挑战。举例来说&#xff0c;…

C#.手术麻醉系统源码 手麻系统如何与医院信息系统进行集成?

C#.手术麻醉系统源码 手麻系统如何与医院信息系统进行集成&#xff1f; 手术麻醉系统与医院信息系统的集成是一个关键步骤&#xff0c;它有助于实现信息的共享和流程的协同&#xff0c;从而提高医疗服务的效率和质量。手麻系统与lis、his、pacs等系统的对接是医院信息化建设的重…

Leetcode 148. 排序链表

心路历程&#xff1a; 这道题通过很简单&#xff0c;但是如果想要用O(1)的空间复杂度O(nlogn)的时间复杂度的话&#xff0c;可能得需要双指针快排的思路。 解法&#xff1a;遍历模拟 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0…

Java基础入门--Java API课后题

五、编程题 1.编写一个每次随机生成 10个 0&#xff08;包括&#xff09; 到 100 之间的随机正整数。 import java.util.Random;public class Example01{public static void main(String[] args) {for(int i0;i<10;i) {System.out.println(new Random().nextInt(0,100));}}…

【黑马头条】-day05延迟队列文章发布审核-Redis-zSet实现延迟队列-Feign远程调用

文章目录 昨日回顾今日内容1 延迟任务1.1 概述1.2 技术对比1.2.1 DelayQueue1.2.2 RabbitMQ1.2.3 Redis实现1.2.4 总结 2 redis实现延迟任务2.0 实现思路2.1 思考2.2 初步配置实现2.2.1 导入heima-leadnews-schedule模块2.2.2 在Nacos注册配置管理leadnews-schedule2.2.3 导入表…

MySQL事务以及并发访问隔离级别

MySQL事务以及并发问题 事务1.什么是事务2.MySQL如何开启事务3.事务提交方式4.事务原理5.事务的四大特性&#xff08;ACID&#xff09; 事务并发问题1.并发引起的三个问题2.事务隔离级别 事务 在 MySQL 中&#xff0c;事务支持是在引擎层实现的。MySQL 是一个支持多引擎的系统&…

Java开发测试(第一篇):Java测试框架JUnit5

目录 1.基本介绍 2.maven中安装JUnit5 3.使用 4.JUnit5命名规则 5.JUnit5常用注解 6.JUnit5断言 7.JUnit5多个类之间的继承关系 8.JUnit5参数化 &#xff08;1&#xff09;使用场景&#xff1a; &#xff08;2&#xff09;使用前需在pom.xml文件中导入依赖 &#xff…

AcWing 1388. 游戏(每日一题)

原题链接&#xff1a;1388. 游戏 - AcWing题库 玩家一和玩家二共同玩一个小游戏。 给定一个包含 N 个正整数的序列。 由玩家一开始&#xff0c;双方交替行动。 每次行动可以在数列的两端之中任选一个数字将其取走&#xff0c;并给自己增加相应数字的分数。&#xff08;双方…

TCP三次握手,四次挥手

TCP为什么四次挥手&#xff1f;而不是三次&#xff1f; 正常流程&#xff1a;服务接收到 客户端的 FIN请求后&#xff0c;会发送一个ACK响应&#xff0c;等待系统资源释放后&#xff0c;再发送FIN 请求给客户端&#xff0c;客户端再发送一个ACK响应。 若为三次&#xff1a;就是…

unsigned和int相加减的错误

先看代码 #include<cstring> #include<vector> using namespace std; int main() {string s "12345678";int n s.length();cout << "n-10" << n - 10 << endl;cout << "s.length() - 10" << s.len…

第九届蓝桥杯大赛个人赛省赛(软件类)真题C 语言 A 组-航班时间

#include<iostream> using namespace std;int getTime(){int h1, h2, m1, m2, s1, s2, d 0;//d一定初始化为0&#xff0c;以正确处理不跨天的情况 scanf("%d:%d:%d %d:%d:%d (%d)", &h1, &m1, &s1, &h2, &m2, &s2, &d);return d …

基于Arduino nano配置银燕电调

1 目的 配置电调&#xff0c;设置电机转动方向&#xff0c;使得CW电机朝顺时针方向转动&#xff0c;CCW电机朝逆时针转动。 2 步骤 硬件 Arduino nano板子及USB线变阻器银燕电调EMAX Bullet 20A朗宇电机 2205 2300KV格氏电池3S杜邦线若干接线端子 软件 BLHeliSuite 注意…

数据库表设计18条黄金规则

前言 对于后端开发同学来说&#xff0c;访问数据库&#xff0c;是代码中必不可少的一个环节。 系统中收集到用户的核心数据&#xff0c;为了安全性&#xff0c;我们一般会存储到数据库&#xff0c;比如&#xff1a;mysql&#xff0c;oracle等。 后端开发的日常工作&#xff…