C语言数据结构专题(3应用-通讯录的实现)

前言

前面的两节我们弄清了顺序表是什么?顺序表是怎么实现的?此时大家可能有疑问了:顺序表被创造出来具体有什么用呢?那么本节就给大家带来顺序表的应用--通讯录的实现,废话不多说,我们正式进入本节的学习

基于顺序表实现通讯录项目

通讯录的前置

我们在日常生活中都使用过通讯录。通讯录里面的一条联系人数据通常会包含以下的内容:

通讯人的姓名、性别、年龄、电话号码、家庭住址等等,通讯录里面通常包含多条联系人数据

之前我们讲解的顺序表的类型是 int 类型的,但是通讯录里面的数据多种多样,仅仅使用 int 类型的顺序表是肯定无法完成通讯录的实现的,我们知道顺序表可以存储 int 、char 等类型的数据,所以顺序表中也可以存入自定义类型的数据,所以此时我们就让顺序表“升级”一下,我们在顺序表中存入结构体,每个结构体里面都包含每个联系人的数据,我们设结构体的名称为 personInfo ,该结构体里面存放联系人的 姓名、性别、年龄、等数据,我们把这些数据称作联系人数据,我们将每一条联系人数据存入数组,我们就可以存储多个联系人数据

通讯录的实现

我们先来定义联系人数据结构:

typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}peoInfo;

我们再在顺序表的头文件里面改一下类型:

将顺序表改成通讯录

定义 Contact.h 文件

我们根据联系人数据来定义一下Contact.h 文件,同时该文件里面包含了通讯录的操作:

#pragma once

#define NAME_MAX 20
#define GENDER_MAX 10 //male female
#define TEL_MAX 20
#define ADDR_MAX 100


//定义联系人数据结构
//姓名 性别 年龄 电话号码 地址
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);
//通讯录的销毁
void ContactDesTory(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录的查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

我们在这里尤其需要注意一下这一步的代码:

typedef struct Seqlist Contact;

对通讯录进行初始化的过程在本质上其就是对顺序表进行初始化,此时我们给顺序表重新命名一下,就把他的名字改成通讯录

我们此时需要修改一下之前顺序表的代码,因为之前顺序表的实现是 int 类型的,而现在通讯录是自定义类型的。之前编写的代码和现在的代码肯定会有所冲突,我们将有冲突的代码直接删除或者注释掉,再适当的更改某些地方的代码,让他不再报错,此时修改过的文件应该如下

Seqlist.h 文件的修改:

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "contact.h"


typedef peoInfo SLDataType;

//动态顺序表
typedef struct Seqlist
{
	SLDataType* arr;
	int size;//有效数据的个数
	int capacity;//空间大小
}SL;

//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestory(SL* ps);
//顺序表的头部 插入 和 删除 + 顺序表的 尾部 插入 和 删除
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);

void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

//顺序表的打印
void SLPrint(SL s);

//在顺序表的指定位置之前插入和删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);

我们需要在该文件里面包含 "contact.h" 文件

Seqlist.c 文件的修改:

​
#define _CRT_SECURE_NO_WARNINGS 1
//静态顺序表
//struct Seqlist
//{
//	int arr[100];
//	int size;//记录顺序表当前有效数据的个数
//
//
//};

//动态顺序表
//struct Seqlist
//{
//	int* arr;
//	int size;//有效的数据个数
//	int capacity;//记录空间大小
//};

#include"Seqlist.h"
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;

}

//顺序表的销毁
void SLDestory(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}

	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}


void SLCheckCapacity(SL* ps)
{
	//插入数据前看空间够不够
	if (ps->capacity == ps->size)
	{
		//申请空间
		//判断capacity是否为0
		int newCapaciy = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapaciy * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
			//直接退出程序,不再继续执行
		}
		//空间申请成功
		ps->arr = tmp;
		ps->capacity = newCapaciy;
	}
}



//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	if (ps == NULL)
	{
		return;
	}
	SLCheckCapacity(ps);
	ps->arr[ps->size] = x;
	++ps->size;
	//或者写作 ps->arr[ps->size++] = x;

}

//头插
void SLPushFront(SL* ps, SLDataType x)
{
	if (ps == NULL)
	{
		return;
	}
	SLCheckCapacity(ps);
	//先让顺序表中的数据向后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//arr[1] = arr[0]
	}
		ps->arr[0] = x;
		ps->size++;
	
}

打印
//void SLPrint(SL s)
//{
//	for (int i = 0; i < s.size; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	printf("\n");
//}

//尾部删除
void SLPopBack(SL* ps)
{
	if (ps == NULL)
	{
		return;
	}

	if (ps->size == 0)
	{
		return;
	}

	--ps->size;

}
//头部删除
void SLPopFront(SL* ps)
{
	if (ps == NULL)
	{
		return;
	}

	if (ps->size == 0)
	{
		return;
	}

	//数据整体前挪
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->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);
	
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}

	ps->size--;
}

顺序表的查找
//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;
//}

​

我们把报错了的代码全部都注释掉,此时的代码如上所示

通讯录的初始化

对通讯录的初始化实际上是要进行顺序表的初始化,顺序表的初始化在之前就已经实现好了,我们可以将其引入 Contact.c 文件中,就可以直接使用了

#include "Seqlist.h"

//通讯录的初始化
void ContactInit(Contact* con)
{
	//实际上是要进行顺序表的初始化
	//顺序表的初始化在之前就已经实现好了
	SLInit(con);
}

通讯录的销毁

对通讯录的销毁其实在本质上就是对顺序表的销毁,所以我们就可以编写出代码如下:

//通讯录的销毁
void ContactDesTroy(Contact* con)
{
	SLDestory(con);
}

通讯录添加数据

我们首先需要在键盘上获取用户的数据:联系人姓名、性别、年龄、电话号码、地址

然后再把它存入通讯录中:

//通讯录添加数据
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);

}

我们此时在 test 文件中测试一下:

void ContactTest01()
{
	Contact con;
	ContactInit(&con);
	ContactAdd(&con);


	ContactDesTory(&con);
}


int main()
{
	ContactTest01();
	return 0;
}

运行成功,没有报错

通讯录删除数据

我们要想删除数据,其前提条件是该数据必须存在,只有存在的数据才能执行删除操作

在删除文件前,我们需要找到联系人信息,我们可以用多种方式去找到联系人信息--可以用姓名、电话号码、住址等,我们就选择通过姓名来找到联系人吧:

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if(0 == strcmp(con->arr[i].name,name));
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;

}

 如果要删除的联系人数据存在,那么我们此时就知道了要删除的联系人数据对应的下标

所以我们此时就可以写出删除联系人的代码:

//通讯录删除数据
void ContactDel(Contact* con)
{
	//数据只有存在才能被删除
	//查找
	char name[NAME_MAX];
	
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人数据不存在\n");
		return;
	}

	//要删除的联系人数据存在--知道了要删除的联系人数据对应的下标
	SLErase(con, find);
	printf("删除成功!\n");
}

展示通讯录数据

我们需要针对类似于表格的形式展示联系人数据,所以我们还需要打印一个表头

//展示通讯录数据
void ContactShow(Contact* con)
{
	//表头:姓名、性别、年龄、电话号码、地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	//展示数据,遍历通讯录,打印每个联系人数据
	for (int i = 0; i < con->size; i++)
	{
		printf("%s %s %d %s %s\n",
			con->arr[i].name,			\
			con->arr[i].gender,			\
			con->arr[i].age,			\
			con->arr[i].tel,		    \
			con->arr[i].addr
		);

	}


}

我们来测试一下:

可以看到它的运行没有出现错误

通讯录的修改

要修改通讯录,其前提是要修改的联系人数据存在

void ContactModify(Contact* con)
{
	//要修改的联系人数据存在
	char name[NAME_MAX];

	printf("请输入要修改的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要修改的联系人数据不存在\n");
		return;
	}
	//直接修改
	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");
}

整体逻辑和删除数据很像。我们接下来来测试一下:

void ContactTest01()
{
	Contact con;
	ContactInit(&con);
	ContactAdd(&con);
	ContactAdd(&con);
	ContactShow(&con);

	/*ContactDel(&con);*/
	ContactModify(&con);
	ContactShow(&con);
	
	ContactDesTory(&con);
}

代码运行成功,没有存在问题

通讯录的查找

之前我们在删除和修改数据的时候定义了一个通过姓名来查找的函数,但它仅仅只能返回数组里面的下标,我们想要通过查找来打印出所有的联系人信息

据此我们可以写出代码如下:

//通讯录的查找
void ContactFind(Contact* con)
{
	char name[NAME_MAX];

	printf("请输入要查找的联系人姓名:\n");
	scanf("%s", name);
	
	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人数据不存在\n");
		return;
	}
	//按照格式打印:
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%3s %3s %3d %3s %3s\n",
		con->arr[find].name,		 \
		con->arr[find].gender,		 \
		con->arr[find].age,			 \
		con->arr[find].tel,			 \
		con->arr[find].addr
	);

}

我们再来测试一下:

查找的功能实现成功

整合通讯录

之前我们在测试的都是单一代码的展现,通讯录是一个完整的功能,我们要把通讯录整合起来,创造一个菜单,来让用户自行选择通讯录的操作,让通讯录的功能变得完整:

void menu()
{
	printf("*************************通讯录***********************\n");
	printf("***********1.增加联系人         2.删除联系人**********\n");
	printf("***********3.修改联系人         4.查找联系人**********\n");
	printf("***********5.展示联系人         0.退出此程序**********\n");
	printf("******************************************************\n");


}




int main(void)
{
	int op = -1;
	Contact con;
	ContactInit(&con);

	do 
	{
		menu();
		printf("请选择您的操作:\n");
		scanf("%d", &op);

		//根据 op 来选择操作
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("退出通讯录...\n");
			break;
		default:
			printf("没有此操作,请重新选择\n");
			break;
		}


	}while(op != 0);

	ContactDesTory(&con);
	return 0;
}

程序包装完美,通讯录功能成功实现

全代码展示

Seqlist.h:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "contact.h"


typedef peoInfo SLDataType;

//动态顺序表
typedef struct Seqlist
{
	SLDataType* arr;
	int size;//有效数据的个数
	int capacity;//空间大小
}SL;

//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestory(SL* ps);
//顺序表的头部 插入 和 删除 + 顺序表的 尾部 插入 和 删除
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);

void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

//顺序表的打印
void SLPrint(SL s);

//在顺序表的指定位置之前插入和删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);

Seqlist.c:

#define _CRT_SECURE_NO_WARNINGS 1
//静态顺序表
//struct Seqlist
//{
//	int arr[100];
//	int size;//记录顺序表当前有效数据的个数
//
//
//};

//动态顺序表
//struct Seqlist
//{
//	int* arr;
//	int size;//有效的数据个数
//	int capacity;//记录空间大小
//};

#include"Seqlist.h"
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;

}

//顺序表的销毁
void SLDestory(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}

	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}


void SLCheckCapacity(SL* ps)
{
	//插入数据前看空间够不够
	if (ps->capacity == ps->size)
	{
		//申请空间
		//判断capacity是否为0
		int newCapaciy = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapaciy * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
			//直接退出程序,不再继续执行
		}
		//空间申请成功
		ps->arr = tmp;
		ps->capacity = newCapaciy;
	}
}



//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	if (ps == NULL)
	{
		return;
	}
	SLCheckCapacity(ps);
	ps->arr[ps->size] = x;
	++ps->size;
	//或者写作 ps->arr[ps->size++] = x;

}

//头插
void SLPushFront(SL* ps, SLDataType x)
{
	if (ps == NULL)
	{
		return;
	}
	SLCheckCapacity(ps);
	//先让顺序表中的数据向后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//arr[1] = arr[0]
	}
		ps->arr[0] = x;
		ps->size++;
	
}

打印
//void SLPrint(SL s)
//{
//	for (int i = 0; i < s.size; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	printf("\n");
//}

//尾部删除
void SLPopBack(SL* ps)
{
	if (ps == NULL)
	{
		return;
	}

	if (ps->size == 0)
	{
		return;
	}

	--ps->size;

}
//头部删除
void SLPopFront(SL* ps)
{
	if (ps == NULL)
	{
		return;
	}

	if (ps->size == 0)
	{
		return;
	}

	//数据整体前挪
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->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);
	
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}

	ps->size--;
}

顺序表的查找
//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;
//}

Contact.h:

#pragma once

#define NAME_MAX 20
#define GENDER_MAX 10 //male female
#define TEL_MAX 20
#define ADDR_MAX 100


//定义联系人数据结构
//姓名 性别 年龄 电话号码 地址
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);
//通讯录的销毁
void ContactDesTory(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录的查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

Contact.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"
#include "Seqlist.h"



//通讯录的初始化
void ContactInit(Contact* con)
{
	//实际上是要进行顺序表的初始化
	//顺序表的初始化在之前就已经实现好了
	SLInit(con);
}

//通讯录的销毁
void ContactDesTory(Contact* con)
{
	SLDestory(con);
}


//通讯录添加数据
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);

}

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if(0 == strcmp(con->arr[i].name,name));
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;

}




//通讯录删除数据
void ContactDel(Contact* con)
{
	//数据只有存在才能被删除
	//查找
	char name[NAME_MAX];
	
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人数据不存在\n");
		return;
	}

	//要删除的联系人数据存在--知道了要删除的联系人数据对应的下标
	SLErase(con, find);
	printf("删除成功!\n");
}

//展示通讯录数据
void ContactShow(Contact* con)
{
	//表头:姓名、性别、年龄、电话号码、地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	//展示数据,遍历通讯录,打印每个联系人数据
	for (int i = 0; i < con->size; i++)
	{
		printf("%3s %3s %3d %3s %3s\n",
			con->arr[i].name,			\
			con->arr[i].gender,			\
			con->arr[i].age,			\
			con->arr[i].tel,		    \
			con->arr[i].addr
		);

	}


}


//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的联系人数据存在
	char name[NAME_MAX];

	printf("请输入要修改的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要修改的联系人数据不存在\n");
		return;
	}
	//直接修改
	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");
}





//通讯录的查找
void ContactFind(Contact* con)
{
	char name[NAME_MAX];

	printf("请输入要查找的联系人姓名:\n");
	scanf("%s", name);
	
	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人数据不存在\n");
		return;
	}
	//按照格式打印:
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%3s %3s %3d %3s %3s\n",
		con->arr[find].name,		 \
		con->arr[find].gender,		 \
		con->arr[find].age,			 \
		con->arr[find].tel,			 \
		con->arr[find].addr
	);

}

test.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Seqlist.h"
#include"contact.h"


//void SLTest01()
//{
//	SL s1;
//	SLInit(&s1);
//	测试尾插代码
//	SLPushBack(&s1, 1);
//	SLPushBack(&s1, 2);
//	SLPushBack(&s1, 3);
//	SLPushBack(&s1, 4);
//	SLPrint(s1);
//	SLPopBack(&s1);
//	SLPrint(s1);
//
//
//	//.....
//	SLDestory(&s1);
//
//}
//
//void SLTest02()
//{
//	SL s1;
//	SLInit(&s1);
//	测试尾插代码
//	SLPushBack(&s1, 1);
//	SLPushBack(&s1, 2);
//	SLPushBack(&s1, 3);
//	SLPushBack(&s1, 4);
//	SLPrint(s1);
//	//测试删除指定位置数据
//	SLErase(&s1, 3);
//	//查找数组中的元素1的下标
//	SLPrint(s1);
//	int find = SLFind(&s1, 8);
//	if (find < 0)
//	{
//		printf("没有找到\n");
//    }
//
//	else 
//	{
//		printf("找到了,下表为%d\n", find);
//	}
//
//	SLDestory;
//
//
//}


//测试通讯录的方法
//void ContactTest01()
//{
//	Contact con;
//	ContactInit(&con);
//	ContactAdd(&con);
//	ContactAdd(&con);
//	ContactShow(&con);
//
//	/*ContactDel(&con);*/
//	ContactModify(&con);
//	ContactShow(&con);
//	ContactFind(&con);
//
//	
//	ContactDesTory(&con);
//}
//
//
//int main()
//{
//	ContactTest01();
//	return 0;
//}

void menu()
{
	printf("*************************通讯录***********************\n");
	printf("***********1.增加联系人         2.删除联系人**********\n");
	printf("***********3.修改联系人         4.查找联系人**********\n");
	printf("***********5.展示联系人         0.退出此程序**********\n");
	printf("******************************************************\n");


}




int main(void)
{
	int op = -1;
	Contact con;
	ContactInit(&con);

	do 
	{
		menu();
		printf("请选择您的操作:\n");
		scanf("%d", &op);

		//根据 op 来选择操作
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("退出通讯录...\n");
			break;
		default:
			printf("没有此操作,请重新选择\n");
			break;
		}


	}while(op != 0);

	ContactDesTory(&con);
	return 0;
}

结尾

我们关于顺序表的应用--通讯录的所有内容到这里就结束了,仔细想想,通讯录的代码还有可以优化的空间--我们可以把通讯录与文件操作结合起来,保证在退出程序以后的联系人信息不丢失,具体操作请自己完成,谢谢您的浏览!!!

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

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

相关文章

探寻马来西亚服务器托管的优势与魅力

随着全球跨境业务的不断增加&#xff0c;境外服务器成为越来越受欢迎的选择。在这其中&#xff0c;马来西亚服务器备受关注&#xff0c;其机房通常位于马来西亚首都吉隆坡。对于客户群体主要分布在东南亚、澳大利亚和新西兰等地区的用户来说&#xff0c;马来西亚服务器是一个理…

MATLAB近红外光谱分析技术应用

郁磊副教授&#xff0c;主要从事MATLAB编程、机器学习与数据挖掘、数据可视化和软件开发、生理系统建模与仿真、生物医学信号处理&#xff0c;具有丰富的实战应用经验&#xff0c;主编《MATLAB智能算法30个案例分析》、《MATLAB神经网络43个案例分析》相关著作。已发表多篇高水…

JVM基础:类的生命周期详解

JDK版本&#xff1a;jdk8 IDEA版本&#xff1a;IntelliJ IDEA 2022.1.3 文章目录 一. 生命周期概述二. 加载阶段(Loading)2.1 加载步骤2.2 查看内存中的对象 三. 连接阶段(Linking)3.1 连接之验证3.2 连接之准备3.3 连接阶段之解析 四. 初始化阶段(Initialization)4.1 单个类的…

约数与倍数-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第45讲。 约数与倍数&#…

rust 面向对象编程特性、模式与模式匹配、高级特征

面向对象编程OOP 学习了结构体、枚举&#xff0c;它们可以包含自定义数据字段&#xff0c;也可以定义内部方法&#xff0c;它们提供了与对象相同的功能。 面向对象的四大特征&#xff1a;封装、继承、多态 通过pub标记为公有的结构体&#xff0c;在其他模块中可以访问使用这…

python爬虫———post请求方式(第十四天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

C语言【编译和链接】

1.程序执行过程 C语言的编译和链接是将源代码转换为可执行程序的过程。下面是C语言编译和链接的基本步骤&#xff1a; 预处理&#xff1a;在编译前&#xff0c;预处理器会对源代码进行。它会处理以"#"开头的预处理指令&#xff0c;#include和#define&#xff0c;并将…

算法笔记————ST表

运用了倍增思想&#xff0c;从小到大处理 1.【模板】ST 表 // Problem: // P3865 【模板】ST 表 // // Contest: Luogu // URL: https://www.luogu.com.cn/problem/P3865 // Memory Limit: 125 MB // Time Limit: 800 ms // // Powered by CP Editor (https://cpedi…

Kotlin学习日志(一)TextView、Button、Toast的使用(1)

android:layout_width“wrap_content” android:layout_height“wrap_content”/> import kotlinx.android.synthetic.main.activity_main.* 这句话的意思是引进Kotlin的的控件变量自动映射功能&#xff0c;接下来只要是这个activity_main.xml文件中的控件&#xff0c;我…

非关系型数据库——Redis基本操作

目录 一、Redis数据库常用命令 1.Set——存放数据 2.Get——获取数据 3.Keys——获取符合条件的键值 4.Exists——判断键值是否存在 5.Del——删除指定键值 6.Type——获取键值对应的类型 7.Rename——对已有键值重命名&#xff08;覆盖&#xff09; 8.Renamenx——对…

160 Linux C++ 通讯架构实战14,epoll 反应堆模型

到这里&#xff0c;我们需要整理一下之前学习的epoll模型&#xff0c;并根据之前的epoll模型&#xff0c;提出弊端&#xff0c;进而整理epoll反应堆模型&#xff0c;进一步深刻理解&#xff0c;这是因为epoll实在是太重要了。 复习之前的epoll的整体流程以及思路。 参考之前写…

虚幻UE5智慧城市全流程开发教学

一、背景 这几年&#xff0c;智慧城市/智慧交通/智慧水利等飞速发展&#xff0c;骑士特意为大家做了一个这块的学习路线。 二、这是学习大纲 1.给虚幻UE5初学者准备的智慧城市/数字孪生蓝图开发教程 https://www.bilibili.com/video/BV1894y1u78G 2.UE5数字孪生蓝图开发教学…

【软件工程】测试规格

1. 引言 1.1简介 本次的测试用例是基于核心代码基本开发完毕&#xff0c;在第一代系统基本正常运行后编写的&#xff0c;主要目的是为了后续开发与维护的便利性。 该文档主要受众为该系统后续开发人员&#xff0c;并且在阅读此文档前最后先阅读本系统的需求文档、概要设计文…

海外视频网站推广实战需掌握的10个关键性数据指标-华媒舍

在海外视频网站推广实战中&#xff0c;了解和掌握一些关键性数据指标是非常重要的。这些指标可以帮助我们评估视频网站的推广效果&#xff0c;优化推广策略&#xff0c;提升用户体验。以下是推广人员在实战中应该了解和关注的十个关键性数据指标&#xff1a; 1. 视频创意点击率…

PS入门|规规矩矩的图形怎么抠出来?

前言 上一次讲解到用魔棒工具蒙版可以把需要的区域抠出来&#xff0c;但仅适用于边缘锐利的类型。 但魔棒工具并不适用于边缘区域有过渡色的内容&#xff0c;比如下面这张照片&#xff1a; 如果直接使用魔棒工具进行选择&#xff0c;就会出现下面这种情况&#xff1a; 在边界…

数据挖掘入门项目二手交易车价格预测之建模调参

文章目录 目标步骤1. 调整数据类型&#xff0c;减少数据在内存中占用的空间2. 使用线性回归来简单建模3. 五折交叉验证4. 模拟真实业务情况5. 绘制学习率曲线与验证曲线6. 嵌入式特征选择6. 非线性模型7. 模型调参&#xff08;1&#xff09; 贪心调参&#xff08;2&#xff09;…

内表GROUP BY

内表GROUP BY REPORT z_test_table_lhy. DATA: price TYPE sflight-price. SELECT MIN( price ) AS m,carridINTO DATA(t_temp)FROM sflightGROUP BY carridHAVING MAX( price ) > 10. "Having从句中比较统计结果时&#xff0c;需要将统计函数重写一遍&#xff0c;而不…

Android数据存储技术

一、文件存储 <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"vertical"android:layout_width"match_parent"android:layout_height"match_parent" ><EditTextandroid:id&qu…

树莓派安装Windows搭建网盘和下载机

0 需求分析 在同一个局域网内&#xff0c;同时有多种设备&#xff08;Windows&#xff0c;Linux&#xff0c;Android&#xff09;需要进行大量的数据共享。另外&#xff0c;还时常需要从百度网盘/夸克网盘等网盘下载文件。不难看出&#xff0c;我的需求很简单&#xff0c;就是…

异常的处理

异常处理概述 在编写程序时&#xff0c;经常要在可能出现错误的地方加上检测的代码&#xff0c;如进行x/y运算时&#xff0c;要检测分母为0&#xff0c;数据为空&#xff0c;输入的不是数据而是字符等。过多的if-else分支会导致程序的代码加长、臃肿&#xff0c;可读性差&…