数据结构之通讯录项目的实现

数据结构之通讯录项目的实现_第1张图片

各位老铁们时隔数日,俺又回来了,今日小试牛刀一把,给大家share 一下,基于顺序表的基础,如何实现通讯录项目???

 欲知后事如何,且看以下分析!

目录

目录


目录

一:基本知识点

二:顺序表的初始化,销毁,增·删·检·查等等一系列操作

三:通讯录涉及到的一些增删检查


在讲通讯录如何实现之前,容我先卖个关子。

一:基本知识点

首先我们需要先了解以下顺序表的相关知识。

1.顺序表是线性表的一种,它在逻辑结构上一定是线性的,但是在物理结构上不一定是线性的。

逻辑结构:也就是我们人为想象的

物理结构:计算机内存存储

2.顺序表是基于数组实现的,但它又不完全同于数组

3.掌握结构体的一些基本常识

4 顺序表是随机存取的,它可以任意访问某一个指定数据

二:顺序表的相关操作

1.结构体的重命名,其实主要就是简化名字,用起来比较方便一些

1.1比如说想把 类型为:struct SeqList 重命名为SL

      typedef struct SeqList SL;

1.2 当我们把自己所写的接口给他人使用时,可能就不仅仅局限于我对int 型数据的处理,我      们不妨做一下优化

    typedef int SLDataType;

    而我们在定义我们数据域的时候需要这样写

     SLDataType* a;

这样写的目的以便于可以实现其他类型

ok~~咱话不多,上代码

数据结构之通讯录项目的实现_第2张图片

 数据结构之通讯录项目的实现_第3张图片

 2.顺序表里面涉及函数的具体实现

2.1)顺序表的初始化

void SLInit(SL *ps)//初始化
{
	ps->a = NULL;//因为ps 是指针 ,所以只能用箭头来访问
	ps->size = ps->capacity = 0;//支持连等
}

2.2)顺序表的销毁

注意我们的free 只适用于释放动态内存开辟的空间(堆),并且所释放的空间不能为空

所以我们就需要进项判断释放为空

void SLDestroy(SL *ps)//销毁
{
	//free 只能适用于动态内存开辟的空间且所free 的空间不能为NULL
	if (ps->a)//判断所指的空间是否为空
	{
		free(ps->a);
		ps->a = NULL;
	}
	ps->capacity = ps->size = 0;
}

2.3)顺序表打印

我们这里只需要遍历整个顺序表即可

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

}

2.4)顺序表的尾插

2.4.1)顺序表有足够的空间可以插入

数据结构之通讯录项目的实现_第4张图片

这时候我们只需要在 size-1 这个下标对应的位置插入即可

2.4.2)当我们空间不足的时候就需要开辟空间

malloc() :向内存申请空间

realloc() :向内存申请一块连续的空间

calloc():向内存申请空间,并把他进行初始化

这时候,需要思考以下,用哪一个来开辟空间

数据结构之通讯录项目的实现_第5张图片

 没错,我们使用realloc()来开辟空间,因为我们不知道自己要具体插入多少个数据,而realloc向内存申请一块连续的空间 

 因为我们在进行头插一系列操作时,都需要判断是否有空间,所以把判断是否有空间写成一个函数

注意这里有一些小细节:

1)SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(newcapacity));

这样写是不对的,因为sizeof()在求大小的时候是以字节为单位的

2)int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;// 初始化之后我size,capacity是为0

这句必须写,若不写当我开辟空间的时候,这个空间大小是0

void SLCheckCapacity(SL* ps)// 空间容量的检查
{
	if(ps->size == ps->capacity)//判断是否有空间
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;// 初始化之后我的size,capacity是为0
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity); // 注意: 头文件的引用;sizeof求空间大小时,是以字节为单位的  这时候所开辟空间的类型SLDataType*
		//空间可能会存在开辟失败的
		if (tmp == NULL)
		{
			perror("malloc\n");
		}
		// 空间开辟成功,进行更新
		ps->a = tmp;
		ps->capacity = newcapacity;

	}
}

 尾插函数的具体实现:

void SLPushBack(SL* ps,SLDataType x)//尾插   注意:这里第二个参数是SLDataType型
{
	assert(ps); //确保指针有效性
	//先确认是否有空间可以插入   不够:扩容    够了:直接插
	SLCheckCapacity(ps);
	//再进行插入
	/*for (int i = 0; i < ps->size; i++)
	{
		ps->a[i] = x;// 对当前第 i 个位置进行插入
		ps->size++;
	}注意当我size= 0,这样写是不可以的
	*/
	ps->a[ps->size++] = x;  //这样写直接一步到位     因为也插入了,size也对应更新了
	//也可以这样写  ps->a[ps->size] = x;ps->size++;
}

 2.5)头插函数的实现

1)这里依然是需要考虑以下是否有空间进行头插

2)如何插入:首先挪动数据——怎么挪?其次进行插入

 从前往后挪:

数据结构之通讯录项目的实现_第6张图片

显然是不行的,从前往后挪动会造成数据的覆盖所以从后往前挪 

数据结构之通讯录项目的实现_第7张图片

思路有了,那我们就代码见吧

void SLPushFront(SL* ps, SLDataType x)//头插
{
	assert(ps);
	//先判断空间是否足够
	SLCheckCapacity(ps);
	// 从后往前移动
	for (int i = ps->size-1; i >= 0 ; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;
	ps->size++;
}

2.6)尾删实现

1)首先我们要确保这不是一个空表->只需要ps-size == 0

2)ps->size :表示当前顺序表数据的有效个数

3)尾删我们只需要让size--即可 

 判空函数:

void SLPopBack(SL* ps)//尾删
{
	assert(ps);
	//判断是不是空表
	/*if (IsEmpty(ps) == 0)
		perror(IsEmpty);*///这样写是不对的
	assert(!IsEmpty(ps));//assert(IsEmpty(ps)) 这样写是不对的  assert()断言是用来判断里面的表达式是真还是假,只有为假的话,这个断言才会生效
	//进行尾删
	ps->size--;// 没有必要进行赋值,直接size--就行
}

2.7)头删实现

1.)首先确定这不是一个空表

2.)数据如何移动?最后别忘了让ps->size--;

 数据结构之通讯录项目的实现_第8张图片

挪动之后的数数据

数据结构之通讯录项目的实现_第9张图片

核心代码: ps->a[i] = ps->a[i + 1];

void SLPopFront(SL* ps)//头删
{
	assert(ps);
	//首先确保不是空表,其次挪动数据:从后往前挪
	assert(!IsEmpty(ps));//问题同上(88)
	for (int i = 0; i size-1 ; i++)
	{
		//最后一次进来 ps->a[size-1-1] = ps->a[size-1]
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

2.8)指定位置插入

这个指定位置插入和前面插入基本上如出一辙,只不过我们需要判断插入位置的有效性

    assert(pos >= 0 && pos <= ps->size);

void SLInsert(SL* ps, int pos, SLDataType x)//指定位置插入
{
	//pos 要在有效的范围内 && 空间是否足够
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	// 进行插入:从后往前移动
	for (int i = ps->size-1; i >pos-1 ;i--)
	{
		// 最后进来 ps->a[pos+1] = ps->a[pos];
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}

2.9)指定位置删除

我们需要考虑位置有效性以及空间是否足够

void SLEarse(SL* ps, int pos)//指定位置删除
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	// 注意是从后往前移动
	for (int i =pos; i < ps->size-1; i++)
	{
		//最后进来的i : ps->size-2     ps->size-2 = ps->size-1;
		ps->a[i] = ps->a[i+1];
	}
	ps->size--;
}

来到这里我们对顺序表的基本操作是已经完成了,下面我们可以通过这个顺序表来实现通讯录这个小项目

三:通讯录的目录

1.联系人添加
2.联系人删除
3.查找联系人
4.打印通讯录
5.联系人修改

通讯录的底层是顺序表,下面就需要我们对顺序表进行一个封装

数据结构之通讯录项目的实现_第10张图片

首先我们需要先考虑以下到底是使用定长数组还是动态数组???

其次我们需要自定义一个通讯录结构体的类型

#pragma once
#define  NAME_MAX 1000
#define SEX_MAX 100
#define TEL_MAX 100
#define ADDR_MAX 100

数据结构之通讯录项目的实现_第11张图片

typedef struct ContactInfo CInfo ;//类型重命名   CInfo

函数的具体实现;

1.)联系人添加
void CInfoAdd(Contact* pcon)//联系人的添加
{
	assert(pcon);//头文件引入
	CInfo info; //先创建一个通讯录这样类型的一个变量info ,info这个变量表示一个联系人对应的所有数据
	printf("请输入要添加联系人的姓名\n");
	scanf("%s", info.name);// 数组名表示首元素地址,无需&
	printf("请输入要添加联系人的性别\n");
	scanf("%s", info.sex);
	printf("请输入要添加联系人的电话\n");
	scanf("%s", info.tel);
	printf("请输入要添加联系人的地址\n");
	scanf("%s",info.addr);
	printf("请输入要添加联系人的年龄\n");
	scanf("%d",&info.age);
	//终端输入一个联系人对应的数据后进行插入(尾插)
	SLPushBack(pcon,info);// 往哪里插,要插入谁的
}
2.)联系人删除

 删除之前,先判断是否为空

ps->size == 0

void CInfoPop(Contact* pcon)//联系人的删除
{
	//先判断是否为空,其次删除
	assert(pcon);
	//SLPopBack(pcon);尾删
	SLPopFront(pcon);//头删
}
3)联系人修改

这里我们先暂时根据用户输入要修改联系人的姓名来操作

首先我们需要先判断此联系人是否存在>其次在对联系人各项具体内容进行修改

这里涉及到strcmp这个函数的应用

数据结构之通讯录项目的实现_第12张图片

int FindByName(Contact* pcon,char name[])
{
	assert(pcon);
	for (int i = 0; i < pcon->size; i++)
	{
		//pcon->a[i].name == name;//注意这样写是不对的的
		//要判断所查找的姓名和我指定要删除的姓名对应的内容都是字符串:strcmp()用来比较字符串大小的,当2个字符串内容一样,此函数返回0
		if(strcmp(pcon->a[i].name,name)== 0)  
			return i;//直接返回该联系人对应的下标
	}
	//没有找到
	return -1;
}
void CInfoModify(Contact* pcon)//联系人的修改
{
	//比如先根据输入联系人姓名来进行修改,首先判断该联系人是否存在

	printf("请输入要修改联系人的姓名\n");
	char name[NAME_MAX];
	scanf("%s",name);//修改之后的内容如何保存?
	int find = FindByName(pcon, name);//find :要修改联系人对应的下标
	if (find < 0)
	{
		printf("该联系人不存在\n");
		return;//没有必要执行下面的代码
	}
	//来到这,此联系人是存在的
	printf("请输入联系人的姓名\n");
	scanf("%s", pcon->a[find].name);
	printf("请输入联系人的性别\n");
	scanf("%s", pcon->a[find].sex);
	printf("请输入联系人的电话\n");
	scanf("%s", pcon->a[find].tel);

	printf("请输入联系人的地址\n");
	scanf("%s", pcon->a[find].addr);

	printf("请输入联系人的年龄\n");
	scanf("%d", &pcon->a[find].age);
	printf("修改联系人已成功\n");

}
4)联系人的查找

思路:先判断该联系人是否存在->若存在则返回此联系人对应的所有信息

int CInfoFind(Contact* pcon)//联系人查找
{
	//根据姓名判断该联系人是否存在,再进行打印
	printf("请输入要查找联系人的姓名\n");
	char name[NAME_MAX];
	scanf("%s", name);//修改之后的内容如何保存?
	int find = FindByName(pcon, name);//find :要修改联系人对应的下标
	if (find < 0)
	{
		printf("该联系人不存在\n");
		return;//没有必要执行下面代码
	}
	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "电话", "地址", "年龄");
	printf("%-5s %-5s %-5s %-5s %-5d\n", pcon->a[find].name,pcon->a[find].sex,pcon->a[find].tel,pcon->a[find].addr,pcon->a[find].age);
}
 5)通讯录的打印

其实这个很简单了,我们只需循环遍历即可

void CInfoPrint(Contact* pcon)//联系人打印
{
	assert(pcon);
	//打印一下我的表头
	printf("%-6s", "姓名");// %-20s -20表示指定输出格式为左对齐&&指定位宽为20  %20s: 表示右对齐&&指定位宽20
	printf("%-6s", "性别");
	printf("%-6s", "电话");
	printf("%-6s", "地址");
	printf("%-6s\n", "年龄");
	for (int i = 0; i < pcon->size; i++)
	{
		printf("%-5s", pcon->a[i].name);
		printf("%-5s", pcon->a[i].sex);
		printf("%-10s", pcon->a[i].tel);
		printf("%-5s", pcon->a[i].addr);
		printf("%-5d\n", pcon->a[i].age);
	}
}

来到这里,说明我们基本已经大功告成了,下面我们只需要进行简单的操作,以菜单形式来呈现出来

通讯录菜单的设计
void ContactMenu()
{
		printf("*****************************************************\n");
		printf("***************1.添加联系人      2.删除联系人********\n");
		printf("***************3.查找联系人      4.修改联系人********\n");
		printf("***************5.打印通讯录      6.退出通讯录********\n");
		printf("****************************************************\n");
}
 Contact.h这个文件对应的代码
#pragma once
#define  NAME_MAX 1000
#define SEX_MAX 100
#define TEL_MAX 100
#define ADDR_MAX 100

typedef struct ContactInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
	int age;
}CInfo;
//通讯录的底层是顺序表实现的
typedef struct SeqList Contact;
//函数的声明
void CInfoInit(Contact* pcon);//初始化
void CInfoDestroy(Contact* pcon);//销毁
void CInfoAdd(Contact* pcon);//联系人的添加
void CInfoPop(Contact* pcon);//联系人的删除
void CInfoPrint(Contact* pcon);//联系人打印
void CInfoModify(Contact* pcon);//联系人的修改
int CInfoFind(Contact* pcon);//指定联系人的查找
Contact.c对应的代码
#include
#include"assert.h"
#include
#include"Contact.h"

void CInfoInit(Contact* pcon)//通讯录的初始化
{
	SLInit(pcon);
}
void CInfoDestroy(Contact* pcon)//通讯录的销毁
{
	SLDestroy(pcon);
}
void CInfoAdd(Contact* pcon)//联系人的添加
{
	assert(pcon);//头文件引入
	CInfo info; //先创建一个通讯录这样类型的一个变量info ,info这个变量表示一个联系人对应的所有数据
	printf("请输入要添加联系人的姓名\n");
	scanf("%s", info.name);// 数组名表示首元素地址,无需&
	printf("请输入要添加联系人的性别\n");
	scanf("%s", info.sex);
	printf("请输入要添加联系人的电话\n");
	scanf("%s", info.tel);
	printf("请输入要添加联系人的地址\n");
	scanf("%s",info.addr);
	printf("请输入要添加联系人的年龄\n");
	scanf("%d",&info.age);
	//终端输入一个联系人对应的数据后进行插入(尾插)
	SLPushBack(pcon,info);// 往哪里插,要插入谁的
}
void CInfoPrint(Contact* pcon)//联系人打印
{
	assert(pcon);
	//打印一下我的表头
	printf("%-6s", "姓名");// %-20s -20表示指定输出格式为左对齐&&指定位宽为20  %20s: 表示右对齐&&指定位宽20
	printf("%-6s", "性别");
	printf("%-6s", "电话");
	printf("%-6s", "地址");
	printf("%-6s\n", "年龄");
	for (int i = 0; i < pcon->size; i++)
	{
		printf("%-5s", pcon->a[i].name);
		printf("%-5s", pcon->a[i].sex);
		printf("%-10s", pcon->a[i].tel);
		printf("%-5s", pcon->a[i].addr);
		printf("%-5d\n", pcon->a[i].age);
	}
}

void CInfoPop(Contact* pcon)//联系人的删除
{
	//先判断是否为空,其次删除
	assert(pcon);
	//SLPopBack(pcon);尾删
	SLPopFront(pcon);//头删
}

int FindByName(Contact* pcon,char name[])
{
	assert(pcon);
	for (int i = 0; i < pcon->size; i++)
	{
		//pcon->a[i].name == name;//注意这样写是不对的的
		//要判断所查找的姓名和我指定要删除的姓名对应的内容都是字符串:strcmp()用来比较字符串大小的,当2个字符串内容一样,此函数返回0
		if(strcmp(pcon->a[i].name,name)== 0)  
			return i;//直接返回该联系人对应的下标
	}
	//没有找到
	return -1;
}
void CInfoModify(Contact* pcon)//联系人的修改
{
	//比如先根据输入联系人姓名来进行修改,首先判断该联系人是否存在

	printf("请输入要修改联系人的姓名\n");
	char name[NAME_MAX];
	scanf("%s",name);//修改之后的内容如何保存?
	int find = FindByName(pcon, name);//find :要修改联系人对应的下标
	if (find < 0)
	{
		printf("该联系人不存在\n");
		return;//没有必要执行下面的代码
	}
	//来到这,此联系人是存在的
	printf("请输入联系人的姓名\n");
	scanf("%s", pcon->a[find].name);
	printf("请输入联系人的性别\n");
	scanf("%s", pcon->a[find].sex);
	printf("请输入联系人的电话\n");
	scanf("%s", pcon->a[find].tel);

	printf("请输入联系人的地址\n");
	scanf("%s", pcon->a[find].addr);

	printf("请输入联系人的年龄\n");
	scanf("%d", &pcon->a[find].age);
	printf("修改联系人已成功\n");

}
int CInfoFind(Contact* pcon)//联系人查找
{
	//根据姓名判断该联系人是否存在,再进行打印
	printf("请输入要查找联系人的姓名\n");
	char name[NAME_MAX];
	scanf("%s", name);//修改之后的内容如何保存?
	int find = FindByName(pcon, name);//find :要修改联系人对应的下标
	if (find < 0)
	{
		printf("该联系人不存在\n");
		return;//没有必要执行下面代码
	}
	printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "电话", "地址", "年龄");
	printf("%-5s %-5s %-5s %-5s %-5d\n", pcon->a[find].name,pcon->a[find].sex,pcon->a[find].tel,pcon->a[find].addr,pcon->a[find].age);
}

 SeqList.h对应的代码
#pragma once

//typedef int SLDataType;
typedef struct ContactInfo SLDataType;//这样子写是不对的:typedef struct CInfo SLDataType 

typedef struct SeqList
{
	SLDataType* a;//可以实现其他类型
	int size;//顺序表的有效个数
	int capacity;//顺序表的容量
}SL;// 重命名

//函数的声明
void SLInit(SL* ps);//初始化
void SLPrint(SL* ps);//打印
void SLDestroy(SL* ps);//销毁
void SLPushBack(SL* ps,SLDataType);//尾插
void SLPopBack(SL* ps);//尾删
void SLPushFront(SL* ps,SLDataType x);//头插
void SLPushFront(SL* ps);//头删
void SLInsert(SL* ps,int pos , SLDataType x);//指定位置插入
void SLEarse(SL* ps, int pos);//指定位置删除



 SeqList.c对应的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include"Contact.h"
#include"assert.h"
#include
#include
#include

//函数的具体实现
void SLInit(SL *ps)//初始化
{
	ps->a = NULL;//因为ps 是指针 ,所以只能用箭头来访问
	ps->size = ps->capacity = 0;
}
void SLDestroy(SL *ps)//销毁
{
	//free 只能适用于动态内存开辟的空间且所free 的空间不能为NULL
	if (ps->a)//判断所指的空间是否为空
	{
		free(ps->a);
		ps->a = NULL;
	}
	ps->capacity = ps->size = 0;//支持连等的
}

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

}

//int SLIsEmpty(SL* ps)
//{
//	if (ps->size == 0)
//	{
//		return 0;//是空表
//	}
//	else
//		return 1;//不是空表
//}
bool IsEmpty(SL* ps)//需要引入头文件
{
	assert(ps);
	return ps->size == 0;//注意return ps->size == ps->capacity ;是不对的,只是用来判空间是否足够的
}

void SLCheckCapacity(SL* ps)// 空间容量的检查
{
	if(ps->size == ps->capacity)//既可以判断是否为空表,也可以判断是否没有空间
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;// 初始化之后我的size,capacity是为0
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newcapacity); // 注意: 头文件的引用;sizeof求空间大小时,是以字节为单位的  这时候所开辟空间的类型SLDataType*
		//空间可能会存在开辟失败的
		if (tmp == NULL)
		{
			perror("malloc\n");
		}
		// 空间开辟成功,进行更新
		ps->a = tmp;
		ps->capacity = newcapacity;

	}
}
void SLPushBack(SL* ps,SLDataType x)//尾插   注意:这里第二个参数是SLDataType型
{
	assert(ps); //确保指针有效性
	//先确认是否有空间可以插入   不够:扩容    够了:直接插
	SLCheckCapacity(ps);
	//再进行插入
	/*for (int i = 0; i < ps->size; i++)
	{
		ps->a[i] = x;// 对当前第 i 个位置进行插入
		ps->size++;
	}注意当我size= 0,这样写是不可以的
	*/
	ps->a[ps->size++] = x;  //这样写直接一步到位     因为也插入了,size也对应更新了
	//也可以这样写  ps->a[ps->size] = x;ps->size++;
}
void SLPopBack(SL* ps)//尾删
{
	assert(ps);
	//判断是不是空表
	/*if (IsEmpty(ps) == 0)
		perror(IsEmpty);*///这样写是不对的
	assert(!IsEmpty(ps));//assert(IsEmpty(ps)) 这样写是不对的  assert()断言是用来判断里面的表达式是真还是假,只有为假的话,这个断言才会生效
	//进行尾删
	ps->size--;// 没有必要进行赋值,直接size--就行
}
void SLPushFront(SL* ps, SLDataType x)//头插
{
	assert(ps);
	//先判断空间是否足够
	SLCheckCapacity(ps);
	// 从后往前移动
	for (int i = ps->size-1; i >= 0 ; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;
	ps->size++;
}
void SLPopFront(SL* ps)//头删
{
	assert(ps);
	//首先确保不是空表,其次挪动数据:从后往前挪
	assert(!IsEmpty(ps));//问题同上(88)
	for (int i = 0; i size-1 ; i++)
	{
		//最后一次进来 ps->a[size-1-1] = ps->a[size-1]
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

void SLInsert(SL* ps, int pos, SLDataType x)//指定位置插入
{
	//pos 要在有效的范围内 && 空间是否足够
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	// 进行插入:从后往前移动
	for (int i = ps->size-1; i >pos-1 ;i--)
	{
		// 最后进来 ps->a[pos+1] = ps->a[pos];
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}
void SLEarse(SL* ps, int pos)//指定位置删除
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	// 注意是从后往前移动
	for (int i =pos; i < ps->size-1; i++)
	{
		//最后进来的i : ps->size-2     ps->size-2 = ps->size-1;
		ps->a[i] = ps->a[i+1];
	}
	ps->size--;
}

 test.c对应的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"Seqlist.h"
#include"Contact.h"

int option = -1;
void ContactMenu()
{
		printf("*****************************************************\n");
		printf("***************1.添加联系人      2.删除联系人********\n");
		printf("***************3.查找联系人      4.修改联系人********\n");
		printf("***************5.打印通讯录      6.退出通讯录********\n");
		printf("****************************************************\n");
}
int main()
{
	Contact info;//定义一个通讯录类型变量
	CInfoInit(&info);//初始化一下通讯录
	do
	{
		ContactMenu();
		printf("请输入您的选择\n");
		scanf("%d", &option);
		switch (option)
		{
		case 1:CInfoAdd(&info);  //注意 case1 这样写是不对的
			break;
		case 2:
			break; CInfoPop(&info);
		case 3:CInfoFind(&info);
			break;
		case 4:CInfoModify(&info);
			break;
		case 5:CInfoPrint(&info);
			break;
		case 6:printf("GoodBye\n");
			break;
		default:printf("输入有误,请重新输入\n");
			break;
		}
	} while (option);
	CInfoDestroy(&info);//销毁
	return 0;
}

大功告成,我们通讯录这个小项目已经完美完成了,要是各位大佬感觉还不错的话,麻烦给个点个赞,我们互关以一下呗~~~

数据结构之通讯录项目的实现_第13张图片

你可能感兴趣的:(数据结构,ci/cd,c++,c语言)