【数据结构项目】通讯录

news2024/10/2 8:33:04

在这里插入图片描述

个人主页点这里~

原文件在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;//指针没有指向任何数据,容量为0
	ps->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.coloradmin.cn/o/1613671.html

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

相关文章

刷代码随想录有感(41):二叉树最小深度

题干&#xff1a; 代码&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), …

CK_Label_V1

CK_Label_v1&#xff08;电池版&#xff09; 产品型号 CK_Label_v1 尺寸 37*65*33.7mm 按键 1 指示灯 1 RGB灯(红/绿/蓝/黄/紫/白/青) 外观颜色 白色 供电方式 5号干电池供电1800mAh&#xff0c;可更换电池 通信方式 无线通信 合规认证 CE, RoHS 工作温度 …

FebHost:CC域名商业和非商业使用的区别

在当今互联网的世界中&#xff0c;域名的选择不仅关乎一个网站的在线身份&#xff0c;更与其背后的商业策略紧密相连。.cc 顶级域&#xff08;TLD&#xff09;作为众多选择之一&#xff0c;其使用方式可分为商业和非商业两大类。 商业用途&#xff1a;当提及.cc域名的商业用途…

使用yum安装pt-query-digest 并分析MySQL慢查询日志

查看慢SQL日志 1、查看慢日志设置 show variables like slow_query_log%; 2、设置慢日志开关 -- 关闭 SET GLOBAL slow_query_log OFF; -- 开启 SET GLOBAL slow_query_log ON; 3、查看慢日志阈值&#xff0c;即SQL执行时间超过阈值后&#xff0c;才会记录在慢日志文件中 …

Springboot的Test单元测试操作

Springboot的Test单元测试操作 简单总结需要操作的步骤 1&#xff0c;导入依赖 2&#xff0c;创建目录&#xff08;目录和启动类的目录保持一致&#xff09; 3&#xff0c;添加注解 4&#xff0c;写方法测试 1&#xff0c;导入依赖 <dependency><groupId>org.spri…

春游江淮 请来池州 | 3天2晚 您的专属高铁游线路来啦

“快乘高铁 趣游池州”3天2晚高铁游主题线路来喽! 各位旅客朋友请注意,连接九华山、黄山、太平湖“两山一湖”的“黄金旅游线”池黄高铁已进入开通倒计时! 本次列车共设池州、九华山、黄山西、黟县东4站。始发站池州,趁着春意正浓,和我们一起快乘高铁,趣游池州吧! DAY1 上午…

冒泡排序c++

题目描述 编程输入n(1≤n≤20)个小于1000非负整数&#xff0c;然后自动按从大到小的顺序输出。&#xff08;冒泡排序&#xff09; 输入 第一行&#xff0c;数的个数n; 第二行&#xff0c;n个非负整数。 输出 由大到小的n个非负整数&#xff0c;每个数占一行。 样例输入 …

使用 kubeadm 进行证书管理

使用 kubeadm 进行证书管理 一&#xff1a;使用 kubeadm 进行证书管理 1.检查证书是否过期 kubeadm certs check-expiration 2.手动续订证书 使用 kubeadm certs renew 命令 可以随时手动续订证书&#xff0c;该命令使用存储在/etc/kubernetes/pki中的 CA (or front-proxy-…

【JVM常见问题总结】

文章目录 jvm介绍jvm内存模型jvm内存分配参数jvm堆中存储对象&#xff1a;对象在堆中创建分配内存过程 jvm 堆垃圾收集器垃圾回收算法标记阶段引用计数算法可达性分析算法 清除阶段标记清除算法复制算法标记压缩算法 实际jvm参数实战jvm调优jvm常用命令常用工具 jvm介绍 Java虚…

【Flutter】多语言方案一:flutter_localizations 与 GetX 配合版

介绍 多语言方案&#xff1a;flutter_localizations 与 GetX 配合版&#xff0c;好处&#xff1a;命令行生成多语言字符串的引用常量类&#xff0c;缺点&#xff1a;切换语言以后&#xff0c;主界面需要手动触发setState&#xff0c;重绘将最新的Locale数据设置给GetMaterialA…

MKS GM50A MFC GUI 软件使用指南GE50A调零原理及步骤PPT

MKS GM50A MFC GUI 软件使用指南GE50A调零原理及步骤PPT

Datax助力轻松迁移SQLServer数据至GreatSQL

1.环境说明 1.1源端SQLSserver 版本IP端口Microsoft SQL Server 2017192.168.140.1601433 1.2目标端GreatSQL 版本IP端口GreatSQL-8.0.32192.168.139.863308 2.安装环境 2.1安装SQLServer环境 环境说明&#xff1a;借助Docker使用镜像启动数据库 2.1.1安装docker 1.安…

【prometheus】k8s集群部署AlertManager实现邮件和钉钉告警

目录 一、AlertManager概述 1.1 alertmanager简介 1.2 AlertManager核心概念 1.2.1 分组 1.2.2 抑制 1.2.3 静默 1.2.4 客户的行为 1.2.5 高可用性 二、Alertmanager部署邮箱告警 2.1 邮箱配置 2.2 Alertmanager global和route路由配置 2.3 部署prometheus和alertM…

如何熟悉一个陌生的业务系统

目录 一、业务层面 1.1 业务背景 1.2 业务系统概括 1.3 使用情况 1.4 业务流程演练 二、技术层面 2.1 技术架构 2.2 存储层 2.3 系统交互 2.4 运维部署 2.5 系统问题 三、总结 不知道你有没有这样的经历&#xff0c;以前维护某个系统的同事因为某些原因不在维护这个系统了&a…

真实世界的密码学(三)

原文&#xff1a;annas-archive.org/md5/655c944001312f47533514408a1a919a 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十一章&#xff1a;用户认证 本章涵盖了 认证人员和数据之间的区别 用户认证&#xff0c;根据密码或密钥对用户进行身份验证。 用户辅助认…

4.21java聊天室项目小结

基本完成了用户的登录注册功能&#xff0c;可以实现用户账号登录和邮箱登录功能&#xff0c;忘记密码通过邮箱发送验证码找回&#xff0c;注册账号功能&#xff0c;并传递给客户端更新数据库的表内容 注册功能&#xff1a; 注册成功后密码进行MD5加密并通过服务器保存到数据库…

Python 密码学实用指南(全)

原文&#xff1a;zh.annas-archive.org/md5/fe5e9f4d664790ea92fb33d78ca9108d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 前言 密码学在保护关键系统和敏感信息方面有着悠久而重要的历史。本书将向您展示如何使用 Python 加密、评估、比较和攻击数据。总的来说&…

Java学习Go(入门)

下载Go 《官网下载golang》 直接点Download&#xff0c;然后根据你自己的操作系统进行下载&#xff0c;我这里以win10为例 安装go 默认安装到C:\Program Files\Go&#xff0c;这里我们可以选择安装到其他盘&#xff0c;也可以选择默认安装。初学者建议直接一路next。 安装完…

07节-51单片机-矩阵键盘

文章目录 1矩阵键盘原理2.扫描的概念3.弱上拉4.实战-实现矩阵键盘对应按钮按下显示对应值4.1配置代码模板 5.键盘锁 1矩阵键盘原理 在键盘中按键数量较多时&#xff0c;为了减少I/O口的占用&#xff0c;通常将按键排列成矩阵形式 采用逐行或逐列的“扫描”&#xff0c;就可以读…

2024团体设计天梯赛(部分题解)

目录 个人总结: L1-1 编程解决一切&#xff08;5分&#xff09; AC代码: L1-2 再进去几个人&#xff08;5分&#xff09; AC代码: L1- 3 帮助色盲&#xff08;10分&#xff09; AC代码: L1- 4 四项全能&#xff08;10分&#xff09; 代码:(9分) L1-4 别再来这么多猫娘了…