C语言实现通讯录(从0-1的项目)

一、前言

1、实现通讯录首先我们要了解并懂得如何通过C语言来完成有关顺序表的实现
2、需要了解的内容:如何使用顺序表结构实现增、删、改、查等操作

二、顺序表的认识和实现

1、什么是顺序表

最基础的数据结构就是数组。

顺序表则是线性表的一种,常见的线性表有:顺序表、链表、栈、队列等。线性表在逻辑上是线性结构,但是在物理上不一定是连续的。

2、顺序表的与数组的不同

顺序表的底层是数组,但是增加了一些封装起来的方法,实现了数组不能实现的一些接口。

3、顺序表的分类
静态顺序表:

使用固定长度的数组存储元素,静态顺序表的缺点就是内存的固定性,大多数情况下会出现内存给大了会造成浪费,给少了不够用的情况,而动态顺序表就很大程度的解决了这个问题。

动态顺序表:

使用变长数组来存储元素,动态顺序表就很大程度的解决了静态顺序表内存浪费和不够用的问题,在创建之初不给值或者给较小值,之后每次出现不够的情况就扩容数组(malloc\calloc\realloc)。

4、实现一个顺序表
创建结构体变量:
typedef int SLtypeDate;//重定义int为SLtypeDate方便后续需要更改数据时使用typedef struct SeqList
{SLtypeDate* arr;int size;//有效数据个数int capcity;//当前最大空间
}SL;//重定义结构体类型为SL
结构体初始化:

在.h文件中先进行声明

//初始化
void SLInit(SL* ps);

然后在.c文件中实现

#include"SeqList.h"//使用前需要引入我们写好的头文件//初始化
void SLInit(SL* ps)
{ps->arr = NULL;//在这个不赋值ps->size = 0;ps->capcity = 0;
}
实现增、删、查、改功能:
(1)增
//将判断空间是否足够封装为一个函数
void SLCheckCapcity(SL * ps)
{if (ps->capcity == ps->size){//判断capcity是否为0int newcapcity = ps->capcity == 0 ? 4 : 2 * ps->capcity;//使用realloc进行扩容SLtypeDate* tmp = (SLtypeDate*)realloc(ps->arr, newcapcity * sizeof(SLtypeDate));//由于realloc是有可能不成功的,所以要进行判断,并且不能直接赋值给结构体,避免原数据丢失if (tmp == NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capcity = newcapcity;}
}
void SLPushBack(SL*ps, SLtypeDate x)
{assert(ps);//插入数据要先判断内存够不够 相等则说明内存不够SLCheckCapcity(ps);ps->arr[ps->size++] = x;
}
//头插
void SLPushFront(SL* ps, SLtypeDate x)
{assert(ps);SLCheckCapcity(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}
//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLtypeDate x)
{assert(ps);//因为是之前所以可以等于assert(pos >= 0 && pos <= ps->size);SLCheckCapcity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}
(2)删
//删除->尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);ps->size--;
}
//删除->头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
//指定位置删除
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);assert(ps->size);for (int i = pos; i < ps->size; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
(3)查
int SLFind(SL* ps, SLtypeDate x)
{int i = 0;int flag = -1;for(i = 0;i<ps->size;i++){if (ps->arr[i] == x){return i;}}return flag;
}
(4)改
//修改
void SLModify(SL* ps, int pos, SLtypeDate x)
{assert(ps);assert(pos >= 0 && pos < ps->size);ps->arr[pos] = x;
}
最后不要忘记销毁创建的空间
//销毁
void SLDestory(SL* ps)
{if (ps->arr){free(ps->arr);}ps->size = 0;ps->capcity = 0;
}
5、测试

这里只进行了部分测试,感兴趣的朋友可以全部测试一遍(个人练习时一定切记写出一个接口就测试一个接口,不要等好多个都写好了再测试,难以发现出现的问题!!!)

void SLTest3()
{SL ps;SLInit(&ps);//测试尾插SLPushBack(&ps, 1);SLPushBack(&ps, 2);SLPushBack(&ps, 3);SLPushBack(&ps, 4);SLPushBack(&ps, 5);SLModify(&ps, 3, 5);//打印函数SLPrint(ps);SLDestory(&ps);
}
int main()
{SLTest3();return 0;
}

三、通讯录的实现

1、通讯录的基本格式

菜单--选择要进行的项目--将用户选择的项目展示给用户

2、借助上面的顺序表实现通讯录
创建结构体变量
//实现通讯录#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 20//创建一个结构体
//其中包含:姓名 性别 年龄 电话 住址typedef struct PersonInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}peoInfo;
结构体初始化

头文件声明

//对通讯录的操作实际是对顺序表的操作
//初始化之前要先给顺序表改个名字 叫通讯录
typedef struct SeqList Contact;//初始化
void ContactInit(Contact* con);

.c文件中实现

void ContactInit(Contact* con)
{//对通讯录的操作实际是对顺序表的操作SLInit(con);
}
(1)增
//插入数据
void ContactAdd(Contact* con)
{//首先创建一个缓冲区用来保存信息peoInfo Info;printf("请输入要添加的联系人姓名:\n");scanf("%s", Info.name);printf("请输入要添加的联系人性别:\n");scanf("%s", Info.gender);printf("请输入要添加的联系人年龄:\n");scanf("%d", &Info.age);printf("请输入要添加的联系人电话:\n");scanf("%s", Info.tel);printf("请输入要添加的联系人住址:\n");scanf("%s", Info.addr);SLPushBack(con,Info);
}
(2)删
void ContactDel(Contact* con) 
{assert(con);char name[NAME_MAX];printf("请输入要删除的联系人姓名:\n");scanf("%s",name);//将查询封装为一个方法,方便后续使用//for (int i = 0; i < con->size; i++)//{//	//strcmp相等返回0,大于返回1,小于返回-1//	if (strcmp(con->arr[i].name, name) == 0)//	{//		SLErase(con, i);//		return i;//	}//}//return -1;int find = FindByName(con,name);if (find < 0){printf("没有找到该联系人,删除失败!\n");}SLErase(con, find);printf("找到了,删除成功!\n");
}
(3)查
//查找成员
void ContactFind(Contact* con)
{assert(con);char name[NAME_MAX];printf("请输入要查找的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("没有找到该联系人!\n");return;}printf("找到了,以下是该联系人信息!\n");printf("姓名\t性别\t年龄\t电话\t地址\n");printf("%s\t%s\t%d\t%s\t%s\n",con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);
}
(4)改
//修改数据
void ContactModify(Contact* con)
{assert(con);assert(con);char name[NAME_MAX];printf("请输入要修改的联系人姓名:\n");scanf("%s", name);int find = FindByName(con, name);if (find < 0){printf("没有找到该联系人,删除失败!\n");}printf("请输入要添加的联系人姓名:\n");scanf("%s", con->arr[find].name);printf("请输入要添加的联系人性别:\n");scanf("%s", con->arr[find].gender);printf("请输入要添加的联系人年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入要添加的联系人电话:\n");scanf("%s", con->arr[find].tel);printf("请输入要添加的联系人住址:\n");scanf("%s", con->arr[find].addr);printf("修改成功!\n");
}
(5)将数据展示给用户
//展示数据
void ContactShow(Contact* 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->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}
}
同样最后不要忘记销毁在此中间创建的结构体以及申请的内存
//销毁
void ContactDestory(Contact* con)
{SLDestory(con);
}

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

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

相关文章

图片改大小尺寸怎么改?几个修改图片尺寸的方法

日常生活和工作中&#xff0c;图片的大小和尺寸对于我们的工作和生活都至关重要&#xff0c;因此我们经常需要调整图片的大小。我们都知道压缩图是一款功能强大的图片在线处理工具&#xff0c;那么用它怎么调整图片大小呢&#xff1f;下面就让我们一起来看一下具体的操作步骤。…

基于Spring Boot的在线考试系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

实时渲染 -- 材质(Materials)

一、自然界中的材质 首先了解下自然界中的材质 如上这幅图&#xff0c;不同的物体、场景、组合&#xff0c;会让我们看到不同的效果。 我们通常认为物体由其表面定义&#xff0c;表面是物体和其他物体或周围介质之间的边界面。但是物体内部的材质也会影响光照效果。我们目前只…

微服务(基础篇-008-es、kibana安装)

目录 05-初识ES-安装es_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p81&vd_source60a35a11f813c6dff0b76089e5e138cc 1.部署单点es 1.1.创建网络 1.2.加载镜像 1.3.运行 2.部署kibana 2.1.部署 2.2.DevTools 3.安装IK分词器 3.1.在线安装ik…

【IP组播】PIM-SM的RP、RPF校验

目录 一&#xff1a;PIM-SM的RP 原理概述 实验目的 实验内容 实验拓扑 1.基本配置 2.配置IGP 3.配置PIM-SM和静态RP 4.配置动态RP 5.配置Anycast RP 二&#xff1a; RPF校验 原理概述 实验目的 实验内容 实验拓扑 1.基本配置 2.配置IGP 3.配置PIM-DM 4.RPF校…

【洛谷 P8695】[蓝桥杯 2019 国 AC] 轨道炮 题解(映射+模拟+暴力枚举+桶排序)

[蓝桥杯 2019 国 AC] 轨道炮 题目描述 小明在玩一款战争游戏。地图上一共有 N N N 个敌方单位&#xff0c;可以看作 2D 平面上的点。其中第 i i i 个单位在 0 0 0 时刻的位置是 ( X i , Y i ) (X_i, Y_i) (Xi​,Yi​)&#xff0c;方向是 D i D_i Di​ (上下左右之一, 用…

基于Spring Boot的餐厅点餐系统

基于Spring Boot的餐厅点餐系统 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 部分系统展示 管理员登录界面 用户注册登录界面 …

股权激励和期权激励对比辨析

文章目录 概念定义 收益方式 风险评估 应用和分析 股权激励和期权激励&#xff0c;两者的区别是什么&#xff0c;本文就来梳理对比一下。 概念定义 股权激励&#xff0c;是指上市公司以本公司股票为标的&#xff0c;对其董事、高级管理人员及其他员工进行的长期性激励。取得…

JVM专题——类文件加载

本文部分内容节选自Java Guide和《深入理解Java虚拟机》, Java Guide地址: https://javaguide.cn/java/jvm/class-loading-process.html &#x1f680; 基础&#xff08;上&#xff09; → &#x1f680; 基础&#xff08;中&#xff09; → &#x1f680;基础&#xff08;下&a…

C++从入门到精通——入门知识

1. C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称都将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的就是对标识符的名…

ST表---算法

相当于二分的思想&#xff0c;一直比较最值 ST的创建 现在创建成功&#xff0c;是应该如何查询的问题 ST表的查询 虽然这两区间有重叠&#xff0c;但是可以一个往前数&#xff0c;一个往后数&#xff0c;互不影响 时间复杂度 创建st表的复杂度为n*logn 使用时的复杂度为O(…

【机器学习】K-近邻算法(KNN)介绍、应用及文本分类实现

一、引言 1.1 K-近邻算法&#xff08;KNN&#xff09;的基本概念 K-近邻算法&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;是一种基于实例的学习算法&#xff0c;它利用训练数据集中与待分类样本最相似的K个样本的类别来判断待分类样本所属的类别。KNN算法…

Golang 哈希表底层实现原理

1、本文讨论Golang的哈希表 Golang哈希表的实现&#xff0c;底层数据结构是数组单链表&#xff0c;链表节点由8个key、value和键的高八位组成的。为了方便理解&#xff0c;先简单看一个图快速理解。 我们来看一下Golang哈希表的结构体定义 简单介绍一下结构体中几个关键的…

.NET CORE 分布式事务(四) CAP实现最终一致性

目录 引言&#xff1a; 1.0 最终一致性介绍 2.0 CAP 2.0 架构预览 3.0 .NET CORE 结合CAP实现最终一致性分布式事务 3.1 准备工作(数据库&#xff0c;本文使用的是MySql) 3.1.1 数据模型 3.1.2 DbContext 3.1.3 数据库最终生成 3.2 Nuget引入 3.3 appsettings.json …

【漏洞复现】极简云 download.php 接口处存在任意文件读取漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

OpenHarmony实战:小型系统平台驱动移植

在这一步&#xff0c;我们会在源码目录//device/vendor_name/soc_name/drivers目录下创建平台驱动。 建议的目录结构&#xff1a; device ├── vendor_name │ ├── drivers │ │ │ ├── common │ │ │ ├── Kconfig # 厂商驱动内核菜单入口 │ …

武汉星起航电子商务公司领航跨境电商新纪元,助力品牌走向全球

在全球经济一体化的时代背景下&#xff0c;跨境电商正成为推动国际贸易增长的重要力量。武汉星起航电子商务有限公司&#xff0c;作为一家专注于提供一站式解决方案的跨境电商服务商&#xff0c;凭借其丰富的实战经验和专业团队&#xff0c;在行业中取得了令人瞩目的成绩。 自…

前端学习<四>JavaScript基础——02-JavaScript入门:hello world

开始写第一行 JavaScript&#xff1a;hello world JS 代码的书写位置在哪里呢&#xff1f;这个问题&#xff0c;也可以理解成&#xff1a;引入 JS 代码&#xff0c;有哪几种方式&#xff1f;有三种方式&#xff1a;&#xff08;和 CSS 的引入方式类似&#xff09; 行内式&…

前端(动态雪景背景+动态蝴蝶)

1.CSS样式 <style>html, body, a, div, span, table, tr, td, strong, ul, ol, li, h1, h2, h3, p, input {font-weight: inherit;font-size: inherit;list-style: none;border-spacing: 0;border: 0;border-collapse: collapse;text-decoration: none;padding: 0;margi…

014——超声波模块驱动开发Plus(基于I.MX6uLL、SR04和poll机制)

目录 一、基础知识 二、分析为什么打印会影响中断 三、驱动程序 四、应用程序 五、验证及其它 一、基础知识 013——超声波模块驱动开发&#xff08;基于I.MX6uLL与SR04&#xff09;-CSDN博客 二、分析为什么打印会影响中断 asmlinkage __visible int printk(const ch…