【数据结构项目】通讯录

在这里插入图片描述

个人主页点这里~

原文件在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.hqwc.cn/news/638206.html

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

相关文章

在PostgreSQL中如何实现分区表以提高查询效率和管理大型表?

文章目录 解决方案1. 确定分区键2. 创建分区表3. 数据插入与查询4. 维护与管理 示例代码1. 创建父表和子表2. 插入数据3. 查询数据 总结 随着数据量的增长&#xff0c;单一的大型表可能会遇到性能瓶颈和管理难题。PostgreSQL的分区表功能允许我们将一个大型表分割成多个较小的、…

一线实战,一次底层超融合故障导致的Oracle异常恢复

背景概述 某客户数据由于底层超融合故障导致数据库产生有大量的坏块&#xff0c;最终导致数据库宕机&#xff0c;通过数据抢救&#xff0c;恢复了全部的数据。下面是详细的故障分析诊断过程&#xff0c;以及详细的解决方案描述&#xff1a; 故障现象 数据库宕机之后&#xff0c…

Docker - 镜像、容器、仓库

原文地址&#xff0c;使用效果更佳&#xff01; Docker - 镜像、容器、仓库 | CoderMast编程桅杆Docker - 镜像、容器、仓库 提示 这个章节涉及到 Docker 最核心的知识&#xff0c;也是在使用过程中最常使用到的&#xff0c;需要重点学习。 什么是Docker镜像、容器、仓库&…

基于STM32的蓝牙小车的Proteus仿真(虚拟串口模拟)

文章目录 一、前言二、仿真图1.要求2.思路3.画图3.1 电源部分3.2 超声波测距部分3.3 电机驱动部分3.4 按键部分3.5 蓝牙部分3.6 显示屏部分3.7 整体 4.仿真5.软件 三、总结 一、前言 proteus本身并不支持蓝牙仿真&#xff0c;这里我采用虚拟串口的方式来模拟蓝牙控制。 这里给…

python爬虫--------requests案列(二十七天)

兄弟姐们&#xff0c;大家好哇&#xff01;我是喔的嘛呀。今天我们一起来学习requests案列。 一、requests____cookie登录古诗文网 1、首先想要模拟登录&#xff0c;就必须要获取登录表单数据 登录完之后点f12&#xff0c;然后点击network&#xff0c;最上面那个就是登录接口…

详解Java中的五种IO模型

文章目录 前言1、内核空间和用户空间2、用户态和内核态3、上下文切换4、虚拟内存5、DMA技术6、传统 IO 的执行流程 一、阻塞IO模型二、非阻塞IO模型三、IO多路复用模型1、IO多路复用之select2、IO多路复用之epoll3、总结select、poll、epoll的区别 四、IO模型之信号驱动模型五、…

VUE运行找不到pinia模块

当我们的VUE运行时报错Module not found: Error: Cant resolve pinia in时 当我们出现这个错误时 可能是 没有pinia模块 此时我们之要下载一下这个模块就可以了 npm install pinia

RattbitMQ安装

1.RabbitMQ是什么? RabbitMQ是消息队列的一种&#xff0c;生态好&#xff0c;好学习&#xff0c;易于理解&#xff0c;时效性强,支持很多不同语言的客户端,扩展性、可用性都很不错。学习性价比非常高的消息队列&#xff0c;适用于绝大多数中小规模分布式系统。 今天先来简单讲…

【webrtc】m114自己实现的PrioritizedPacketQueue及优先级处理

G:\CDN\WEBRTC-DEV\libwebrtc_build\src\modules\pacing\prioritized_packet_queue.h跟m98不同 :webrtc】m98 RoundRobinPacketQueue的优先级处理,m114直接使用taskqueue顺序处理了。甚至自己实现了优先级队列感觉简化了实现,更为清晰 易读,但是去掉了码率低就优先的逻辑。1…

ChatGPT基础(三) 让ChatGPT回答质量提高十倍的提示词模版

上篇文章介绍了ChatGPT使用提示词的一些方法策略和如何优化我们的提示词。这里呢&#xff0c;我介绍一下参照大佬的方法总结的一个提示词的一个用法的模板。使用这个模板之后&#xff0c;我们的提问和获得答案的效率和收集素材的完整度能提高很多。 首先我介绍一下这个模板&am…

R: 阿尔法α多样性计算和箱图制作,以及差异分析

# install.packages("vegan") library(vegan) library(ggplot2) library(ggpubr)setwd("xxx") # 使用read.table()函数读取数据 df <- read.table("xxx", header TRUE, row.names 1)# 转置数据框 df <- t(df)# 计算每个样品的香农多样性…

面试(06)————MySQL篇

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