数据结构·顺序表应用

        本节应用是要用顺序表实现一个通讯录,收录联系人的姓名、性别、电话号码、住址、年龄

                        ​​​​​​​        

        顺序表的实现在上一节中已经完成了,本节的任务其实就是应用上节写出来的代码的那些接口函数功能,做出来一个好看的,可视化的东西

        首先把准备工作做好,创立好通讯录的头文件Contest.h和源文件Contest.c还有测试源文件,再把上一节的顺序表文件链接过来,在这节中直接使用上节的函数功能

        ​​​​​​​        ​​​​​​​        

1. 通讯录数据类型

        首先我们在Contect.h文件中把通讯录结构体写出来,再改一个好写的名字

                        

                这边数组长度是用宏定义的,为了方便以后更改

2. 通讯录操作方法

        现在我们写一下通讯录的操作发方法,跟之前的写法一样,写一个菜单函数,然后用do···while和switch语句让用户选择要进行什么操作

        在Contect.c文件中写menu()函数,并包含上它的头文件Contect.h

  

        用户操作方案,写在test.c中:

   

        

3. 顺序表改成通讯录

        现在我们要将上节的顺序表稍加修改,将arr中的元素从int型改成通讯录结构体型的,此时,需要在SeqList.h中包含上Contect.h

        修改一下SLDatatype的表示对象为Info就完成了

4. 通讯录里提供的操作

        这个时候我们需要用到SeqList文件中的内容了,但是我们不能在Contest.h中引用SeqList.h了,这样会导致头文件嵌套问题,你包含我,我包含你,没完没了,程序就出错了,所以我们的头文件包含要定好一个顺序,就像这样

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

        确定好这个顺序了,那我们如何使用SeqList.h文件中的内容呢,此时的解决方法就是前置声明,因为内容在后面,但是我们要在前面使用它,所以我们可以在前面声明一下这个内容,就可以在前面使用它了

        ​​​​​​​        

        前置声明之后再改个名字,从顺序表改成通讯录,方便后边辨识和使用

        这时我们运行一下会发现喜提一大堆错误,这时不要慌,问题就出现在之前顺序表的查找和打印函数上了,它们的类型错误导致的报错,我们只需要把它们注释掉就可以了

4.1 通讯录的初始化和销毁

        这块功能非常简单,我们只需要复用SeqList.h中的函数就可以

        ​​​​​​​        

                

        然后在测试文件中调试一下

        发现没问题,该创建的东西都创建好了

4.2 "增""删""查""改""查看通讯录"

4.2.1 "增"

        首先创建一个临时变量info暂时存放一个人的所有信息,然后复用函数就可以了

        在把增的功能添加到主函数之前,我们要在do···while外边写好创建、初始化和销毁通讯录顺序表的功能

        ​​​​​​​        ​​​​​​​        

        然后把ContectAdd()函数放到"增"的位置就好了

        ​​​​​​​        ​​​​​​​        

4.2.2 "查看通讯录"

        先写查看通讯录用来方便检验之后的代码

        然后把这个功能加到main函数里头

4.2.3 "查"

        查找的话可以通过那5个方面去查,这里我就写一个通过名字查的

        这个FindByName()函数因为后面还要用,所以就单拎出来写的,注意用到了字符串操作函数,要引用一下头文件。

4.2.4 "删"

    

4.2.5 "改"

5. 完整代码

Contect.h完整代码

//通讯录数据类型
#define NAME_MAX 100
#define GENDER_MAX 10
#define TEL_MAX 12
#define ADDR_MAX 100
typedef struct PersonInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
	int age;
}Info;

//通讯录菜单
void menu();

//使用顺序表的前置声明
struct SeqList;
typedef struct SeqList Contect;

//通讯录里提供的操作
//通讯录的初始化和销毁
void ContectInit(Contect* pcon);
void ContectDestory(Contect* pcon);


//增、删、改、查、查看通讯录
//增
void ContectAdd(Contect* pcon);

//查看通讯录
void ContectShow(Contect* pcon);

//查
void ContectFind(Contect* pcon);

//删
void ContectDel(Contect* pcon);

//改
void ContectModify(Contect* pcon);

Contect.c完整代码

#include"SeqList.h"

//通讯录菜单
void menu()
{
	printf("******************通讯录*******************\n");
	printf("*********1.添加联系人 2.删除联系人*********\n");
	printf("*********3.修改联系人 4.查找联系人*********\n");
	printf("*********5.查看通讯录 0.退出通讯录*********\n");
	printf("*******************************************\n");
}



//通讯录里提供的操作
//通讯录的初始化和销毁
void ContectInit(Contect* pcon)
{
	SLInit(pcon);
}
void ContectDestory(Contect* pcon)
{
	SLDestory(pcon);
}


//增、删、改、查、查看通讯录
//增
void ContectAdd(Contect* pcon)
{
	//创建一个通讯录结构体用来临时存放一个人的所有信息
	Info info;
	printf("请输入联系人姓名:>");
	scanf("%s", info.name);
	printf("请输入联系人性别:>");
	scanf("%s", info.gender);
	printf("请输入联系人电话:>");
	scanf("%s", info.tel);
	printf("请输入联系人地址:>");
	scanf("%s", info.addr);
	printf("请输入联系人年龄:>");
	scanf("%d", &info.age);

	//保存到通讯录顺序表中
	SLPushBack(pcon, info);
}

//查看通讯录
void ContectShow(Contect* pcon)
{	
	for (int i = 0; i < pcon->size; i++)
	{
		printf("-------------------------------\n");
		printf("姓名:%s\n", pcon->arr[i].name);
		printf("性别:%s\n", pcon->arr[i].gender);
		printf("电话:%s\n", pcon->arr[i].tel);
		printf("地址:%s\n", pcon->arr[i].addr);
		printf("年龄:%d\n", pcon->arr[i].age);
	}
}

//查
#include<string.h>
int FindByName(Contect* pcon, char name[])
{
	for (int i = 0; i < pcon->size; i++)
	{
		if (strcmp(pcon->arr[i].name, name) == 0)
		{
			//找到了
			return i;
		}
	}
	//没找到
	return -1;
}

void ContectFind(Contect* pcon)
{
	char name[NAME_MAX];
	printf("请输入要查找的人名:>");
	scanf("%s", name);

	int ret = FindByName(pcon, name);
	if (ret < 0)
	{
		printf("要查找的联系人不存在!\n");
		return;
	}
	//找到了,打印一下查找的联系人的信息
	printf("-------------------------------\n");
	printf("姓名:%s\n", pcon->arr[ret].name);
	printf("性别:%s\n", pcon->arr[ret].gender);
	printf("电话:%s\n", pcon->arr[ret].tel);
	printf("地址:%s\n", pcon->arr[ret].addr);
	printf("年龄:%d\n", pcon->arr[ret].age);
}


//删
void ContectDel(Contect* pcon)
{
	//删除前先查找,找到了可以删,找不到不能删
	printf("请输入要删除的联系人姓名:>");
	char name[NAME_MAX];
	scanf("%s", name);

	int ret = FindByName(pcon, name);
	if (ret < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	//执行删除操作
	SLErase(pcon, ret);
	printf("删除成功\n");
}


//改
void ContectModify(Contect* pcon)
{
	//修改前先查找,找到了改,找不到不能改
	printf("请输入要修改的联系人姓名:>");
	char name[NAME_MAX];
	scanf("%s", name);

	int ret = FindByName(pcon, name);
	if (ret < 0)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	//执行修改操作
	printf("开始修改!\n");

	printf("请输入姓名:>");
	scanf("%s", pcon->arr[ret].name);
	printf("请输入性别:>");
	scanf("%s", pcon->arr[ret].gender);
	printf("请输入电话:>");
	scanf("%s", pcon->arr[ret].tel);
	printf("请输入地址:>");
	scanf("%s", pcon->arr[ret].addr);
	printf("请输入年龄:>");
	scanf("%d", &pcon->arr[ret].age);

	printf("联系人修改成功!\n");
}

SeqList.h完整代码

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contect.h"

typedef Info SLDatatype;

typedef struct SeqList
{
	SLDatatype* arr;	//存储数据的底层结构
	int capacity;		//记录顺序表的空间大小
	int size;			//有效数据个数
}SL;

//初始化和销毁
void SLInit(SL* ps);
void SLDestory(SL* ps);
//void SLPrint(SL* ps);

//顺序表插入数据
//从尾部插入
void SLPushBack(SL* ps, SLDatatype x);
//从头部插入
void SLPushFront(SL* ps, SLDatatype x);

//顺序表删除数据
//从尾部删除
void SLPopBack(SL* ps);
//从头部删除
void SLPopFront(SL* ps);

//顺序表任意位置增删数据
//指定位置前面增加数据
void SLInsert(SL* ps, int pos, SLDatatype x);
//删除指定位置数据
void SLErase(SL* ps, int pos);


//在顺序表中查找x
//int SLFind(SL* ps, SLDatatype x);

//在顺序表中把pos位置的数据改成x
void SLChange(SL* ps, int pos, SLDatatype x);

SeqList.c完整代码

#include"SeqList.h"

//初始化和销毁	
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

void SLDestory(SL* ps)
{
	assert(ps);
	if (ps->arr)//arr不是空的再释放,也可以不判断
	{
		free(ps->arr);//free空指针函数什么都不会做
	}	
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

//void SLPrint(SL* ps)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		printf("%d ", ps->arr[i]); 
//	}
//	printf("\n");
//}


//顺序表插入数据
//判断空间是否足够,不够就扩容
void SLCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)//空间不够时
	{
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		//为了防止扩容失败导致数据丢失,扩容后的空间地址先不给ps->arr
		SLDatatype* tmp = (SLDatatype*)realloc(ps->arr, newCapacity * sizeof(SLDatatype));
		if (tmp == NULL)//扩容失败
		{
			printf("realloc fail!\n");
			exit(1);//错误退出码1
		}
		//扩容成功
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}

//从尾部插入
//逻辑:空间足够就直接尾插,空间不够就扩容,扩容一般是扩容当前空间的2倍
void SLPushBack(SL* ps, SLDatatype x)
{
	assert(ps);

	//判断空间够不够,不够就扩容
	SLCheckCapacity(ps);

	//走到这里时空间肯定够了,直接在后面插入数据
	ps->arr[ps->size++] = x;
	//ps->size++;
}

//从头部插入
//逻辑:将所有数据向后挪一位,再在第一位插入数据
void SLPushFront(SL* ps, SLDatatype x)
{
	assert(ps);

	//判断空间够不够,不够就扩容
	SLCheckCapacity(ps);

	//此时空间够了,将所有数据往后挪一位,再放数据
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}
//在添加完元素之后一定要记得 ps->size 增加一个

//顺序表删除数据
//从尾部删除
//逻辑:顺序表为空,不能执行删除,顺序表不为空直接删最后一个数据
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--;
}
//在删除完数据之后也要记得减size


//顺序表任意位置增删数据
//指定位置前面增加数据
void SLInsert(SL* ps, int pos, SLDatatype x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);

	//pos及之后的数据往后挪一位
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

//删除指定位置数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

	//pos以后的数据向前挪一位
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}



//在顺序表中查找x
//int SLFind(SL* ps, SLDatatype x)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			return i;//找到了返回下标
//		}
//	}
//	return -1;//没找到返回-1
//}


//在顺序表中把pos位置的数据改成x
void SLChange(SL* ps, int pos, SLDatatype x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	ps->arr[pos] = x;
}

        最后,这套代码是用完一次之后里面存的联系人信息就没了,这时我们可以借助文件操作函数,将数据保存下来,这样下次打开的时候还能加载出来

C语言·文件操作-CSDN博客文章浏览阅读923次,点赞24次,收藏21次。本节介绍了文件的用处,如何用文件指针打开和关闭文件,流的读写函数fgetc fputc fgets fputs fscanf fprintf fread fwrite,和字符串的的格式化输入输出函数sscanf sprintf控制文件指针实现随机读写的函数fseek ftell rewind,文件结束相关函数feof ferror,文件缓冲区的概念https://blog.csdn.net/atlanteep/article/details/134894644?spm=1001.2014.3001.5501

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1.电子基础

https://www.falstad.com/circuit/circuitjs.html vcc&#xff1a;正极 三角形&#xff1a;负极 理想电路原件 电压源、电流源 电压源&#xff1a;正负号表示电压方向 电流源&#xff1a;箭头表示电流方向

2024PMP考试新考纲-【过程领域】近期典型真题和很详细解析(9)

华研荟继续为您分享【过程Process领域】的新考纲下的真题&#xff0c;帮助大家体会和理解新考纲下PMP的考试特点和如何应用所学的知识和常识&#xff08;经验&#xff09;来解题&#xff0c;并且举一反三&#xff0c;一次性3A通过2024年PMP考试。 2024年PMP考试新考纲-【过程领…

Drivable 3D Gaussian Avatars 论文笔记

Drivable 3D Gaussian Avatars 论文笔记 主要的算法架构和贡献是什么&#xff1f;如何使用这个deformation 呢&#xff1f; 主要的算法架构和贡献是什么&#xff1f; 这篇文章主要使用了两个当前流行的概念&#xff0c;一是3D高斯溅射&#xff0c;二是cage-based deformation。…

java SSM政府采购管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM政府采购管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代 码和数据库&#xff0c;系统主要采…

DC-7靶机做题记录

靶机下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1w2c_QKd_hOoR2AzNrdZjMg?pwdtdky 提取码&#xff1a;tdky 参考&#xff1a; DC7靶机地址&#xff1a;http://www.five86.com/downloads/DC-7.zipDC7靶场介绍: https://www.vulnhub.com/entry/dc-7,356/…

Matlab/simulink风储调频,多台飞轮储能调频,风电场调频,飞轮储能带有虚拟惯量和下垂控制,三机九节点系统一次调频,离散模型

上述为不同飞轮储能容量配比&#xff0c;风电场容量配比&#xff0c;以及有无附加频率控制的飞轮储能出力分析。 飞轮储能驱动电机为永磁同步机电机PMSG 有无飞轮储能容量较小&#xff0c;所以对频率的改善效果有限&#xff0c;不过可以继续增大容量&#xff0c;从而增大频率的…

数据结构之顺序表的增删查改

别丢了你的勇敢 前言&#xff1a; 自今日起&#xff0c;我们正式越过C语言的大山&#xff0c;走向了数据结构的深山&#xff0c;现如今摆在我们面前的第一个坎就是顺序表&#xff0c;我们需要了解顺序表的定义&#xff0c;并且知道&#xff0c;如何对其进行增删查改&#xff0…

unicloud 云对象 schema

目录 云对象 创建云对象 客户端调用 二、Schema&#xff08;表结构&#xff09; 什么是Schema&#xff1f; 如何编写DB Schema Schema的一级节点 客户端直连数据库 字段属性 字段类型bsonType 默认值defaultValue/forceDefaultValue 云对象 创建云对象 云对象&#…

智能算法 | Matlab实现改进黑猩猩优化算法SLWCHOA与多个基准函数对比与秩和检验

智能算法 | Matlab实现改进黑猩猩优化算法SLWCHOA与多个基准函数对比与秩和检验 目录 智能算法 | Matlab实现改进黑猩猩优化算法SLWCHOA与多个基准函数对比与秩和检验预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现改进黑猩猩优化算法SLWCHOA与多个基准函数…

mqtt连接阿里云

参考文章&#xff1a;https://blog.csdn.net/fang_dz999/article/details/112283742?app_version6.2.5&codeapp_1562916241&csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22112283742%22%2C%22source%22%3A%22mantouyouy…

JAVA中TreeSet集合的两种排序方法:自然排序和比较器排序

TreeSet支持2种排序&#xff1a;自然排序、比较器排序。 由于TreeSet对内部元素的排序的方法有2种&#xff1a;自然顺序排序、比较器排序。 所以&#xff0c;如果TreeSet采用自然顺序排序&#xff0c;需要内部的元素&#xff08;即自定义类型&#xff09;实现Comparable接口。…

前后对比效果展示的视频怎么制作?左右对比PR模板 Before and After v.2

10种表现方式&#xff0c;前后对比效果展示视频制作PR模板 Before and After v.2 如果您想比较两个图像或视频&#xff0c;这个Adobe Premiere Pro模板非常适合您。只需将两个文件拖放到媒体中&#xff0c;就可以开始了。 适合PS处理图片后期修图前后对比&#xff0c;AI绘图效果…

企业Oracle1 数据库管理

Oracle的安装 一、基础表的创建 1.1 切换到scott用户 用sys 账户 登录 解锁scott账户 alter user scott account unlock;conn scott/tiger;发现并不存在scott账户&#xff0c;自己创建一个&#xff1f; 查找资料后发现&#xff0c;scott用户的脚本需要自己执行一下 C:\ap…

FDM3D打印系列——宝可梦妙蛙种子

fdm打印妙蛙种子 大家好&#xff0c;我是阿赵。   每次打印3D模型&#xff0c;都有新的感觉&#xff0c;这次打印了个宝可梦里面的妙蛙种子&#xff0c;也就是俗称的蒜头王八。   先来看看成果&#xff0c;然后在后面再聊一下关于3D打印的一些体会。使用创想三维的Sermoon …

Linux内核pinctrl子系统驱动框架

一. 简介 本文简单了解一下Linux内核代码中&#xff0c; pinctrl子系统的驱动实现。 注意&#xff1a;本文会涉及到 Linux 驱动分层与分离、平台设备驱动等还未讲解的知识 &#xff0c;所以&#xff0c;也不会影响后续的实验。 二. Linux内核pinctrl子系统驱动 1. probe函…

C++笔记之bool类型的隐式转换现象与应用

C++笔记之bool类型的隐式转换现象与应用 —— 《C++ Primer Plus》 文章目录 C++笔记之bool类型的隐式转换现象与应用1.C++中,有几种类型和表达式可以隐式转换为bool类型2.使用explicit关键字来声明显示转换运算符,这样只有在使用static_cast<bool>时才能将对象转换为…

蓝桥杯理历年真题 —— 数学

1. 买不到的数目 这道题目&#xff0c;考得就是一个日常数学的积累&#xff0c;如果你学过这个公式的话&#xff0c;就是一道非常简单的输出问题&#xff1b;可是如果没学过&#xff0c;就非常吃亏&#xff0c;在考场上只能暴力求解&#xff0c;或是寻找规律。这就要求我们什么…

vue中的插槽

在vue中&#xff0c;有的名词听着高大上&#xff0c;挺怪异的&#xff0c;比如插槽&#xff0c;就是slot&#xff0c;它的作用是为了解决组件之间写的内容在组件中的使用问题。 一、插槽的作用 <!DOCTYPE html> <html> <head><title>Vue中的插槽</…

nginx虚拟主机

虚拟主机指的就是一个独立的站点配置&#xff0c;是nginx默认支持的一个功能&#xff0c;它能够有自己独立的域名&#xff0c;独立的ip&#xff0c;独立的端口配置&#xff0c;能够配置完整的www服务&#xff0c;列如网站搭建&#xff0c;邮件服务器代理等等。并且nginx支持多虚…

Macos数据库管理软件:Navicat Premium for Mac 16.3.5中文版

Navicat Premium 16 for Mac是一款强大的数据库管理和开发工具&#xff0c;支持多种数据库系统&#xff0c;如MySQL、Oracle、SQL Server等。它提供了直观的用户界面和丰富的功能&#xff0c;使用户能够轻松地创建、管理和维护数据库。 软件下载&#xff1a;Navicat Premium fo…