【数据结构项目】通讯录

在这里插入图片描述

个人主页点这里~

原文件在gitee里~


通讯录的实现

  • 基于动态顺序表实现通讯录项目
    • 1、功能要求
    • 2、代码实现
      • file.h
      • file.c
      • List.h
      • List.c
      • test.c

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

准备:结构体、动态内存管理、顺序表、文件操作

1、功能要求

①能够存储100个人的通讯信息
②能够保存用户信息:名字、性别、年龄、电话、地址等
③增加、删除、查找、修改联系人
④显示联系人信息

2、代码实现

当我们将程序关闭时我们可以使用文件流的方法存储通讯录,使得通讯录信息不会丢失
我们在实现通讯录的时候,底层逻辑其实还是顺序表,我们将顺序表稍作修改,然后作为整个项目的其中一个.c文件和一个.h文件
我在实现的过程中,把顺序表相关文件命名为file,通讯录相关文件命名为List,调试文件为test,然后file就是上文顺序表中写出的代码稍加修改,本文对顺序表内容不做过多介绍,详细请参阅上文顺序表

file.h

#pragma once
#define INIT_CAPACITY 4
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "List.h"
typedef PeoInfo 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 SLFindByName(SL* ps, char* x);

file.c

#define _CRT_SECURE_NO_WARNINGS
#include "file.h"
void SLInit(SL* ps)
{ps->a = NULL;//将指针a置为空ps->capacity = 0;//指针没有指向任何数据,容量为0ps->size = 0;//同上,无数据,为0
}
void SLDestroy(SL* ps)
{if (ps->a){free(ps->a);//释放a指向堆区的内存ps->a = NULL;//将a指针置为空}if (ps->capacity)ps->capacity = 0;if (ps->size)ps->size = 0;
}
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", *(ps->a + i));}
}
void SLCheckCapacity(SL* ps)
{if (ps->capacity == ps->size){int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//ss//检查capacity是否为0,若为0,则开辟一块空间,若不为0,则将空间扩大一倍SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));//使用realloc函数开辟动态内存if (tmp == NULL){perror(tmp);return 1;}ps->a = tmp;ps->capacity = newCapacity;}
}
void SLPushFront(SL* ps, SLDataType x)
{if (ps->a)//确保不为空第一种方法{SLCheckCapacity(ps);for (int i = ps->size; i > 0; i--){*(ps->a + i) = *(ps->a + i - 1);//从最后一位与空位开始交换,直到第一位空出来}*ps->a = x;//填补第一位ps->size++;}
}
void SLPopFront(SL* ps)
{if (ps->a){for (int i = 0; i < ps->size - 2; i++){*(ps->a + i) = *(ps->a + i + 1);}ps->size--;//将size减一最后一位就不会被访问到,将其在数组中删除}
}
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);*(ps->a + ps->size++) = x;//后置++先赋值后++,在最后一位放入x,然后size+1
}
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);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->a + ps->size) = *(ps->a + ps->size - 1);//将要插入的数字位置后的所有数字往后移一位,然后插入}*(ps->a + 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->a[i] = ps->a[i+1];}//将所有指定位置以后的数字往前一位ps->size--;//直接删除最后一位
}
int SLFindByName(SL* ps, char* x)
{for (int i = 0; i < ps->size; i++){if (strcmp(x, ps->a[i].name) == 0) // 使用 strcmp 函数来比较字符串  {return i;} // 如果找到匹配项,返回其索引  }return -1; // 如果未找到,返回 -1  
}

List.h

#pragma once
#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[20];char sex[20];int age;char tel[20];char addr[20];
}PeoInfo;//定义一个用户信息结构体并重命名为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);

List.c

#define _CRT_SECURE_NO_WARNINGS
#include "List.h"
#include "file.h"
//初始化通讯录
void InitContact(contact* con)
{SLInit(con);//直接调用顺序表的方法,初始化通讯录
}
//添加通讯录数据
void AddContact(contact* con)
{PeoInfo i;//定义一个通讯录用户printf("请输入联系人姓名:\n");scanf("%s", i.name);printf("请输入联系人性别:\n");scanf("%s", i.sex);printf("请输入联系人年龄:\n");scanf("%d", &i.age);printf("请输入联系人电话:\n");scanf("%s", i.tel);printf("请输入联系人地址:\n");scanf("%s", i.addr);SLPushBack(con, i);
}
//删除通讯录数据
void DelContact(contact* con)
{char name[NAME_MAX];printf("请输入要删除的联系人姓名:\n");scanf("%s", name);//输入一个名字int f = SLFindByName(con, name);//使用SLFindByName函数找出这个名字对应的下标if (f < 0){printf("要删除的联系人数据不存在!\n");return;//找不到就退出}SLErase(con, f);//找到就将它使用指定位置删除函数printf("删除成功!\n");
}
//展示通讯录数据
void ShowContact(contact* con)
{printf("%5s %5s %5s %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");for (int i = 0; i < con->size; i++){printf("%5s %5s %5d %5s %5s\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)
{char name[NAME_MAX];printf("请输入要查找的联系人:\n");scanf("%s", name);int f = SLFindByName(con, name);if (f < 0){printf("不存在\n");return;}printf("%5s %5s %5s %5s %5s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%5s %5s %5d %5s %5s\n",con->a[f].name,con->a[f].sex,con->a[f].age,con->a[f].tel,con->a[f].addr);
}
//修改通讯录数据
void ModifyContact(contact* con)
{char name[NAME_MAX];printf("请输入需要修改的联系人姓名:\n");scanf("%s", name);int f = SLFindByName(con, name);//原理同上if (f < 0){printf("不存在\n");return;}printf("新姓名:\n");scanf("%s", con->a[f].name);printf("新性别:\n");scanf("%s", con->a[f].sex);printf("新年龄:\n");scanf("%d", &con->a[f].age);printf("新电话:\n");scanf("%s", con->a[f].tel);printf("新地址:\n");scanf("%s", con->a[f].addr);printf("修改完成!\n");
}
//销毁通讯录数据
void DestroyContact(contact* con)
{SLDestroy(con);//直接调用顺序表销毁
}

test.c

#include "file.h"
#include "List.h"void Test()
{contact con;InitContact(&con);AddContact(&con);ShowContact(&con);AddContact(&con);ShowContact(&con);AddContact(&con);ShowContact(&con);DelContact(&con);ShowContact(&con);FindContact(&con);ModifyContact(&con);ShowContact(&con);DestroyContact(&con);
}
int main()
{Test();return 0;
}

调试结果:
在这里插入图片描述
在这里插入图片描述

今天就分享到这里了~


在这里插入图片描述

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

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

相关文章

arm版Linux下安装大数据集群各种组件

背景&#xff1a;由于本人是用的Macbookpro m2来进行开发的&#xff0c;很多环境和Intel芯片的都不一样&#xff0c;期间安装各种软件遇到各种问题&#xff0c;为了以后不走之前的老路&#xff0c;现记录各种软件的安装步骤。 系统安装组件说明 序号组件名称组件版本1jdkjdk-…

如何部署npm私有仓库以及在项目中如何使用

如何部署npm私有仓库以及在项目中如何使用 为什么要部署npm私有仓库&#xff1f; 安全性&#xff1a;私有仓库允许团队存放内部研发的、不宜公开发布的代码包&#xff0c;只对特定用户或者团队可见和可用&#xff0c;从而保护公司的知识产权和商业秘密。模块的复用性&#xf…

Oracle进阶(2)——物化视图案例延伸以及序列、同义词

一、物化视图 物化视图&#xff08;Materialized View&#xff09;是 Oracle 数据库中的一个对象&#xff0c;它是一个预先计算和存储的查询结果集&#xff0c;类似于视图&#xff0c;但与视图不同的是&#xff0c;物化视图会将查询结果保存在物理存储中&#xff0c;而不是动态…

C语言练习——上三角矩阵

前言 今天我们来看看如何使用代码实现上三角矩阵吧。首先我们来了解一下上上三角矩阵是什么&#xff0c;上三角矩阵就是在矩阵从左上到右下的对角线之下的数组元素都为0的数组方矩阵&#xff0c;例如&#xff1a; 以一个三阶矩阵为例&#xff0c;在对角线元素之下&#xff0c;就…

面试(06)————MySQL篇

目录 问题一&#xff1a;在MySQL中&#xff0c;如何定位慢查询&#xff1f; 方案一&#xff1a;开源工具 方案二&#xff1a;MySQL自带慢日志 模拟面试 问题二&#xff1a;这个SQL语句执行很慢&#xff0c;如何分析的呐&#xff1f; 模拟面试 问题三&#xff1a;了解过索引…

OpenCV从入门到精通实战(七)——探索图像处理:自定义滤波与OpenCV卷积核

本文主要介绍如何使用Python和OpenCV库通过卷积操作来应用不同的图像滤波效果。主要分为几个步骤&#xff1a;图像的读取与处理、自定义卷积函数的实现、不同卷积核的应用&#xff0c;以及结果的展示。 卷积 在图像处理中&#xff0c;卷积是一种重要的操作&#xff0c;它通过…

ES中文检索须知:分词器与中文分词器

ElasticSearch (es)的核心功能即为数据检索&#xff0c;常被用来构建内部搜索引擎或者实现大规模数据在推荐召回流程中的粗排过程。 ES分词 分词即为将doc通过Analyzer切分成一个一个Term&#xff08;关键字&#xff09;&#xff0c;es分词在索引构建和数据检索时均有体现&…

【力扣 Hot100 | 第六天】4.21(最长连续序列)

文章目录 10.最长连续序列10.1题目10.2解法&#xff1a;哈希法10.2.1哈希思路10.2.2代码实现 10.最长连续序列 10.1题目 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时…

葡萄书--关系图卷积神经网络

异质图和知识图谱 同质图与异质图 同质图指的是图中的节点类型和关系类型都仅有一种 异质图是指图中的节点类型或关系类型多于一种 知识图谱 知识图谱包含实体和实体之间的关系&#xff0c;并以三元组的形式存储&#xff08;<头实体, 关系, 尾实体>&#xff0c;即异…

Python 全栈安全(二)

原文&#xff1a;annas-archive.org/md5/712ab41a4ed6036d0e8214d788514d6b 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第二部分&#xff1a;认证与授权 本书的第二部分是最具商业价值的部分。我这样说是因为它充满了大多数系统需要具备的实用工作流示例&#xf…

Python 全栈安全(四)

原文&#xff1a;annas-archive.org/md5/712ab41a4ed6036d0e8214d788514d6b 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十五章&#xff1a;内容安全策略 本章涵盖 使用 fetch、navigation 和 document 指令编写内容安全策略 使用 django-csp 部署 CSP 使用报…

Redis 内存策略

目录 1. key到期的情况 Redis的内存结构redisDb Redis怎么知道哪个key过期的 Redis对过期key的删除策略 惰性删除 周期删除 2. key未到期&#xff0c;但内存使用已达上限的情况 Redis检查内存阈值的时刻 达到内存上限&#xff0c;Redis淘汰key的策略 结构体redisObj…

【测试】Kali Linux 渗透安全学习笔记(4) - 单一服务器扫描

距离上次做 Kali Linux 分享已经相隔半年之久了&#xff0c;刚好需要主导公司每半年一次的本地安全加固工作&#xff0c;这次将简单分享自己是如何做单一服务器的扫描。 声明&#xff1a; 本文测试的站点为自家站点仅做学习使用&#xff0c;不存在侵犯网络信息安全问题&#…

【C语言】——内存函数的使用及模拟实现

【C语言】——内存函数的使用及模拟实现 前言一、 m e m c p y memcpy memcpy 函数1.1、函数功能&#xff08;1&#xff09;函数名理解&#xff08;2&#xff09;函数介绍 1.2、函数的使用1.3、函数的模拟实现 二、 m e m m o v e memmove memmove 函数2.1、函数功能2.2、函数的…

HarmonyOS开发环境搭建 移动开发 鸿蒙开发 ArkTS

&#x1f4dc;目录 &#x1f4a1; 环境搭建 &#x1f680;安装nodejs &#x1f935;安装ohpm &#x1f354;安装SDK &#x1f4a5;Emulator安装 &#x1f336;️新建ArkTs项目 &#x1f3c6;️ArkTS语言 ✨️基本语法 &#x1f388; 声明式UI描述 &#x1f371;组件 …

java的单元测试和反射

单元测试 就是针对最小的功能单元&#xff0c;编写测试代码对其进行正确性测试 Junit单元测试框架&#xff1a; 可以用来对方法进行测试 有点&#xff1a; 可以灵活的编写测试代码&#xff0c;可以针对某个方法进行测试&#xff0c;也支持一键完成对全部方法的自动发测试&a…

理解JMM

JMM 对volatile的理解 volatile 是java虚拟机提供轻量级的同步机制 1、保证可见性 2、不保证原子性 3、禁止指令重排 那么可见性与JMM相关 什么是JMM Java内存模型&#xff0c;不存在的东西&#xff0c;是一个概念&#xff0c;是一个约定 线程加锁前&#xff0c;必须读取…

uni-app 如何添加模拟器

uni-app 如何添加模拟器 使用微信开发者工具运行微信小程序使用 HBuilderX 内置模拟器使用第三方 Android 模拟器 下载并安装&#xff1a;配置环境&#xff1a;连接模拟器&#xff1a; 总结 有哪些可以使用的安卓模拟器软件 uni-app 如何添加模拟器 Uni-App 是一个基于 Vue.js…

认知觉醒 PDF电子版 下载

认知觉醒 PDF电子版 开启自我改变的原动力 周岭 / 人民邮电出版社 / 2020-10 链接&#xff1a;https://pan.baidu.com/s/1EHUK_AhvE5TWAZsYXFQ5QA?pwdwrho 提取码&#xff1a;wrho

基于IIoT的设备预测性维护设计

基于IIoT的设备预测性维护设计 一、引言 在工业物联网&#xff08;IIoT&#xff09;的背景下&#xff0c;设备预测性维护成为了一种关键的战略&#xff0c;能够帮助企业提前发现并解决设备故障&#xff0c;从而提高生产效率、减少停机时间&#xff0c;并降低总体维护成本。为了…