用顺序表实现通讯录

前言

       这次的通讯录是基于上一篇的动态顺序表的基础上实现的,如果对动态顺序表不熟悉,可以打开这个链接阅读http://t.csdnimg.cn/9zJ5g,这里我们会调用动态顺序表的函数。
如果想看静态顺序表实现通讯录,可以打开这个链接阅读http://t.csdnimg.cn/iC4a6

代码最终的效果图

现在我来带大家实现一下~~

Contact.h

       在创建通讯录的时候,我们需要定义一个结构体来保存用户信息。

#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TELE 20
#define MAX_ADDR 50typedef struct PeopleInformation
{char name[MAX_NAME];char gender[MAX_GENDER];int age;char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInfo;

       由于后续的函数实现是通讯录基于顺序表来实现的,所以我们的通讯录需要使用到顺序表的一些接口函数,为了凸显通讯的特点,我们可以使用contact来重新定义顺序表的名字,这里使用前置声明。

typedef struct SeqList contact;

我们实现通讯录是基于顺序表,所以我们在顺序表添加Contact.h这个头文件。
由于上面我们提到,要使用contact来重新定义顺序表的名字,我们不能直接使用SL,是因为我们的Contact.h是没有包含SeqList.h的,而且也不能包含(两个头文件是不能相互包含的,否则会发生冲突,编译器会报错),由于没有包含SeqList.h,所以只能使用struct SeqList来进行外置声明。

通讯录函数的实现

初始化和导入上回的数据

       如果上次的通讯录是由数据的,我们可以导入进来,这里使用了文件操作函数。

void PushContact(contact* con)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){printf("未导入上次的通讯录的数据\n");return;}int i = 0;int ret = 0;while (1){SLCheckCapacity(con);ret = fread(&con->data[i], sizeof(PeoInfo), 1, pf);if (ret == 0){break;}con->size++;i++;}fclose(pf);pf = NULL;
}

我们在进行初始化的时候,进行初始化,再导入上次通讯录的数据。

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

销毁和保存数据

在销毁通讯录(将内存的通讯录数据清空)之前,我们可以将内存中储存的数据先保留在文件中,方便下次使用。

void DestroyContact(contact* con)
{SaveContact(con);SLDestroy(con);
}

还是要使用文件操作函数来保留数据:

void SaveContact(contact* con)
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("fopen");return;}int i = 0;for (i = 0; i < con->size; i++){fwrite(&con->data[i], sizeof(PeoInfo), 1, pf);}fclose(pf);pf = NULL;printf("已保存好通讯录!\n");
}

添加数据

顺序表有三个插入函数,大家可以自由发挥,这里我调用了尾插函数。

void AddContact(contact* con)
{PeoInfo tmp;printf("请输入添加人的姓名:");scanf("%s", tmp.name);printf("请输入添加人的性别:");scanf("%s", tmp.gender);printf("请输入添加人的年龄:");scanf("%d", &tmp.age);printf("请输入添加人的电话:");scanf("%s", tmp.tele);printf("请输入添加人的地址:");scanf("%s", tmp.addr);//采用尾插SLPushBack(con, tmp);printf("添加成功\n");
}

删除数据

顺序表有三个删除函数,大家可以自由发挥,这里我调用了尾删函数。

void DelContact(contact* con)
{//采用尾删SLPopBack(con);printf("删除成功\n");
}

展示数据

void ShowContact(contact* con)
{assert(con);int i = 0;if (con->size == 0){printf("通讯录为空\n");return;}printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");for (i = 0; i < con->size; i++){printf("%s %s %d %s %s\n", con->data[i].name, con->data[i].gender, con->data[i].age,con->data[i].tele, con->data[i].addr);}printf("\n");
}

这里我先判断了一下通讯录是否有数据,有我才打印,没有我就提示一下。

查找数据

这里的通讯录结构体包含姓名、性别、年龄、电话和地址,我这里是通过姓名来查找的,这里大家可以自由发挥。

要注意姓名查找是字符串进行比较,需要调用strcmp函数,也就是需要用到string.h这个头文件,需要包含一下这个头文件。

void FindContact(contact* con)
{char name[MAX_NAME];printf("输入你要查找的姓名:");scanf("%s", name);int find = SLFind(con, name);if (find >= 0){printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%s %s %d %s %s\n", con->data[find].name,con->data[find].gender,con->data[find].age,con->data[find].tele,con->data[find].addr);}else{printf("查无此人\n");}printf("\n");
}

修改数据

这里的修改数据我是先通过查找你要修改的名字找到对应的数据,再进行修改,这里大家也可以自由发挥。

void ModifyContact(contact* con)
{char name[MAX_NAME];printf("输入你要修改的姓名:");scanf("%s", name);int find = SLFind(con, name);if (find < 0){printf("此人不存在\n");return;}printf("请输修改人的姓名:");scanf("%s", con->data[find].name);printf("请输入修改人的性别:");scanf("%s", con->data[find].gender);printf("请输入修改人的年龄:");scanf("%d", &con->data[find].age);printf("请输入修改人的电话:");scanf("%s", con->data[find].tele);printf("请输入修改人的地址:");scanf("%s", con->data[find].addr);printf("修改成功\n");
}

菜单实现

       写完上述程序之后,我们就可以进行封装了,我们可以写一个简易的小菜单来提供选择,让用户自行使用。

void menu()
{printf("***********          欢迎来到通讯录         ***********\n");printf("***********   1.增加联系人   2.删除联系人   ***********\n");printf("***********   3.查找联系人   4.修改联系人   ***********\n");printf("***********   5.展示通讯录   0.退出通讯录   ***********\n");printf("*******************************************************\n");
}

接着我们来实现主程序实现通讯录这个小程序

int main()
{int option = 0;contact peo;InitContact(&peo);do{menu();printf("请选择:");scanf("%d", &option);switch (option){case 1:AddContact(&peo);break;case 2:DelContact(&peo);break;case 3:FindContact(&peo);break;case 4:ModifyContact(&peo);break;case 5:ShowContact(&peo);break;case 0:printf("退出通讯录\n");DestroyContact(&peo);break;default:printf("输入错误!\n");break;}} while (option);return 0;
}

最终是代码

Contact.h

#pragma once#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TELE 20
#define MAX_ADDR 50typedef struct PeopleInformation
{char name[MAX_NAME];char gender[MAX_GENDER];int age;char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInfo;//前置声明
typedef struct SeqList contact;//初始化通讯录
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);//保存通讯录的数据
void SaveContact(contact* con);//导入上次的通讯录的数据
void PushContact(contact* con);

SeqList.h

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"
#include <string.h>typedef PeoInfo SLDataType;
#define MAX_CAPACITY 4typedef struct SeqList
{SLDataType* data;int size;int capacity;
}SL;void SLInit(SL* ps);//顺序表初始化
void SLDestroy(SL* ps);//顺序表销毁//插入
void SLPushBack(SL* ps, SLDataType x);//尾插//删除
void SLPopBack(SL* ps);//尾删//扩容
void SLCheckCapacity(SL* ps);//查找
int SLFind(SL* ps, char* x);

Contact.c

#include "SeqList.h"//初始化通讯录
void InitContact(contact* con)
{SLInit(con);PushContact(con);
}//销毁通讯录数据
void DestroyContact(contact* con)
{SaveContact(con);SLDestroy(con);
}//添加通讯录数据
void AddContact(contact* con)
{PeoInfo tmp;printf("请输入添加人的姓名:");scanf("%s", tmp.name);printf("请输入添加人的性别:");scanf("%s", tmp.gender);printf("请输入添加人的年龄:");scanf("%d", &tmp.age);printf("请输入添加人的电话:");scanf("%s", tmp.tele);printf("请输入添加人的地址:");scanf("%s", tmp.addr);//采用尾插SLPushBack(con, tmp);printf("添加成功\n");
}//展示通讯录数据
void ShowContact(contact* con)
{assert(con);int i = 0;if (con->size == 0){printf("通讯录为空\n");return;}printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");for (i = 0; i < con->size; i++){printf("%s %s %d %s %s\n", con->data[i].name, con->data[i].gender, con->data[i].age,con->data[i].tele, con->data[i].addr);}printf("\n");
}//删除通讯录数据
void DelContact(contact* con)
{//采用尾删SLPopBack(con);printf("删除成功\n");
}//查找通讯录数据
void FindContact(contact* con)
{char name[MAX_NAME];printf("输入你要查找的姓名:");scanf("%s", name);int find = SLFind(con, name);if (find >= 0){printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%s %s %d %s %s\n", con->data[find].name,con->data[find].gender,con->data[find].age,con->data[find].tele,con->data[find].addr);}else{printf("查无此人\n");}printf("\n");
}//修改通讯录数据
void ModifyContact(contact* con)
{char name[MAX_NAME];printf("输入你要修改的姓名:");scanf("%s", name);int find = SLFind(con, name);if (find < 0){printf("此人不存在\n");return;}printf("请输修改人的姓名:");scanf("%s", con->data[find].name);printf("请输入修改人的性别:");scanf("%s", con->data[find].gender);printf("请输入修改人的年龄:");scanf("%d", &con->data[find].age);printf("请输入修改人的电话:");scanf("%s", con->data[find].tele);printf("请输入修改人的地址:");scanf("%s", con->data[find].addr);printf("修改成功\n");
}//保存通讯录的数据
void SaveContact(contact* con)
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("fopen");return;}int i = 0;for (i = 0; i < con->size; i++){fwrite(&con->data[i], sizeof(PeoInfo), 1, pf);}fclose(pf);pf = NULL;printf("已保存好通讯录!\n");
}//导入上次的通讯录的数据
void PushContact(contact* con)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){printf("未导入上次的通讯录的数据\n");return;}int i = 0;int ret = 0;while (1){SLCheckCapacity(con);ret = fread(&con->data[i], sizeof(PeoInfo), 1, pf);if (ret == 0){break;}con->size++;i++;}fclose(pf);pf = NULL;
}

SeqList.c

#include"SeqList.h"void SLInit(SL* ps)//顺序表初始化
{ps->data = NULL;ps->size = ps->capacity = 0;
}void SLDestroy(SL* ps)//顺序表销毁
{assert(ps);free(ps->data);ps->data = NULL;ps->size = ps->capacity = 0;
}//插入
void SLPushBack(SL* ps, SLDataType x)//尾插
{assert(ps);SLCheckCapacity(ps);ps->data[ps->size++] = x;
}//删除
void SLPopBack(SL* ps)//尾删
{assert(ps);assert(ps->size);ps->size--;
}//扩容
void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? MAX_CAPACITY : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->data, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc fail");exit(1);}ps->data = tmp;ps->capacity = newcapacity;}
}//查找
int SLFind(SL* ps,  char* x)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){if (strcmp(ps->data[i].name, x) == 0){return i;}}return -1;
}

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 option = 0;contact peo;InitContact(&peo);do{menu();printf("请选择:");scanf("%d", &option);switch (option){case 1:AddContact(&peo);break;case 2:DelContact(&peo);break;case 3:FindContact(&peo);break;case 4:ModifyContact(&peo);break;case 5:ShowContact(&peo);break;case 0:printf("退出通讯录\n");DestroyContact(&peo);break;default:printf("输入错误!\n");break;}} while (option);return 0;
}

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

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

相关文章

Linux+HA高可用24X7的安全保证

一&#xff0e; 介绍作为服务器&#xff0c;需要提供一定的24X7的安全保证&#xff0c;这样可以防止关键节点的宕机引起系统的全面崩溃。利用OpenSource开源软件&#xff0c;完成系统的高可靠双机热备方案。基于linux的 HA软件可靠稳定&#xff0c;比使用商业版本的HA软件降低成…

CMakeLists.txt编写简单介绍:CMakeLists.txt同时编译.cpp和.cu

关于CMakeLists.txt的相关介绍,这里不赘诉,本人的出发点是借助于CMakeLists.txt掌握基本的C++构建项目流程,下面是本人根据网络资料以及个人实践掌握的资料。 CMakeList.txt构建C++项目 下图是一个使用CUDA实现hello world的项目,一般来说,一个标准的C++项目包括三个文件…

python标准数据类型--列表常用方法

在Python中&#xff0c;列表&#xff08;List&#xff09;是一种非常常用的数据类型&#xff0c;用于存储一组有序的元素。Python提供了许多内置方法来操作列表&#xff0c;使得对列表的处理变得非常灵活和便捷。在本篇博客中&#xff0c;我们将介绍一些常用的列表方法&#xf…

基本数据类型、包装类与字符串间的转换

&#xff08;1&#xff09;基本数据类型转为字符串 方式1&#xff1a;调用字符串重载的valueOf()方法 int a 10; //String str a;//错误的String str String.valueOf(a);方式2&#xff1a;更直接的方式 int a 10;String str a "";&#xff08;2&#xff09;…

COCO格式转YOLO格式训练

之前就转换过好几次&#xff0c;每次换设备训练&#xff0c;由于压缩包太大&#xff0c;u盘不够用。每次都要找教程从网上再下载一遍。因此这里记录一下&#xff0c;以免下次重新找教程。 在coco数据集中&#xff0c;coco2017train或coco2017val数据集中标注的目标(类别)位置在…

C++--对象作为返回值-----拷贝构造函数不执行的问题解决方案

1.问题现象 本来func函数返回p1&#xff0c;实际上p1会先拷贝一份传递给test函数里面的p,这个时候会执行拷贝构造函数&#xff0c;但是实际上的输出并没有&#xff1b; 而且执行拷贝构造函数的时候&#xff0c;因为生成p1的副本&#xff0c;所以我们打印的地址应该不相同&…

vue3源码解析——watch和watchEffect区别

watch和watchEffect是Vue 3.0中新增的两个响应式API&#xff0c;用于监听数据的变化。watch适用于需要获取新值和旧值&#xff0c;或者需要懒执行的场景&#xff0c;而watchEffect适用于需要监听多个数据源&#xff0c;并且需要立即执行的场景。它们之间的区别如下&#xff1a;…

CSS层叠样式表学习(文本属性)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS文本属性的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 四、CSS文本属性 4.1 文本颜色 4.2 对齐文本 4.3 装饰文本 4.4 文本缩进 4.5 行间距 4.6 文本…

苍穹外卖学习笔记(一)开发环境搭建

苍穹外卖技术框架 网关层&#xff1a; Nginx:反向代理负载均衡 nginx学习&#xff0c;看这一篇就够了&#xff1a;下载、安装。使用&#xff1a;正向代理、反向代理、负载均衡。常用命令和配置文件,很全-CSDN博客应用层&#xff1a; Spring Boot&#xff1a;简化spring程序的创…

计算机内存是如何管理的

计算内存的那些事儿——内存管理 大家回忆一下&#xff0c;计算机结构&#xff0c;或者说一个SoC&#xff08;system-on-chip&#xff09;芯片的结构。 cpu、memory、peripherals&#xff0c;这是计算机的主要部件&#xff0c;三者之间通过system bus勾搭在一起。 The main co…

第五篇:3.4 用户归因和受众(User attribution and audience) - IAB/MRC及《增强现实广告效果测量指南1.0》

翻译计划 第一篇概述—IAB与MRC及《增强现实广告效果测量指南》之目录、适用范围及术语第二篇广告效果测量定义和其他矩阵之- 3.1 广告印象&#xff08;AD Impression&#xff09;第三篇广告效果测量定义和其他矩阵之- 3.2 可见性 &#xff08;Viewability&#xff09;第四篇广…

Vulnhub:BOSSPLAYERSCTF: 1

目录 信息收集 arp nmap nikto whatweb WEB web信息收集 dirmap 命令执行漏洞 反弹shell 提权 系统信息收集 get root 信息收集 arp ┌──(root㉿ru)-[~/kali/vulnhub] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:50:56:2f:dd:9…

找不到api-ms-win-crt-runtime-l1-1-0.dll,无法继续执行代码的解决方法

当电脑系统中关键文件“api-ms-win-crt-runtime-l1-1-0.dll”发生丢失情况时&#xff0c;会导致某些应用程序无法正常运行。api-ms-win-crt-runtime-l1-1-0.dll是Windows操作系统中至关重要的动态链接库&#xff08;DLL&#xff09;文件&#xff0c;它包含了应用程序在运行过程…

【java探索之旅】逻辑控制掌握 顺序结构 分支语句

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、逻辑控制的概念二、顺序结构三、分支结构3.1 if语句3.2 if习题巩固3.3 细节注意项…

【个人笔记】如何用 Python 编写激活码解锁程序,方法二

目录 前言 第一步&#xff1a;编写激活码解锁程序&#xff08;激活码.py&#xff09; 第二步&#xff1a;修改需要解锁的程序&#xff08;1.py&#xff09; 总结 前言 在软件开发中&#xff0c;有时我们需要设计一种机制来保护程序&#xff0c;例如通过激活码来控制程序的…

Cortex-M7 异常处理与返回

1 前言 当CM3开始响应一个中断时&#xff0c;会在它小小的体内奔涌起三股暗流&#xff1a;  入栈&#xff1a; 把8个寄存器的值压入栈;  取向量&#xff1a;从向量表中找出对应的服务程序入口地址;  选择堆栈指针MSP/PSP&#xff0c;更新堆栈指针…

C语言 | Leetcode C语言题解之第2题两数相加

题目&#xff1a; 题解&#xff1a; struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {struct ListNode *head NULL, *tail NULL;int carry 0;while (l1 || l2) {int n1 l1 ? l1->val : 0;int n2 l2 ? l2->val : 0;int sum n1 n2 …

「每日跟读」英语常用句型公式 第3篇

「每日跟读」英语常用句型公式 第3篇 1. I don’t know how to ____ 我不知道如何_____ I don’t know how to play soccer (我不知道怎么踢足球) I don’t know how to study&#xff08;我不知道如何学习&#xff09; I don’t know how to play chess (我不知道如何下国…

使用 Kafka 保证消息不丢失的策略及原理解析

✨✨祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 一、引言 二. 持久化存储 2.1持久化存储原理&#xff1a; 2.2使用示例&#xff1a; …

数据结构:详解【树和二叉树】

1. 树的概念及结构&#xff08;了解&#xff09; 1.1 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝…