C语言顺序表实践项目:通讯录

目录

前言

目标

一. 准备工作

1. 创建必要文件 

2. 确定文件包含关系 

 3. 设计通讯录结构体

4. 重命名顺序表为通讯录

5. 对通讯录结构的理解 

二. 函数实现

1. 初始化 ContactInit

2. 销毁 ContactDestroy

3. 添加数据 ContactAdd

4. 按姓名查找 FindByName

5. 删除数据 ContactDel

6. 修改 ContactModify

7. 查找 ContactFind

8. 展示数据ContactShow

9. 保存数据 SaveContact

10. 读取数据 ReadContact

11. 增容 SLCheckCapacity

12. 菜单 menu

13. 主函数 main

三. 参考代码

Contact.h

Contact.c

SeqList.h

SeqList.c

test.c

写在最后


前言

前面我们介绍了如何用C语言实现动态顺序表,现在,我们基于之前写好的代码,编写一个通讯录项目。

目标

1.实现通讯录的增删查改

2.读取和保存通讯录的数据

注意:本篇基于上一篇用C语言实现顺序表,如果对顺序表不了解,请一定要阅读上一篇文章,否则本篇的理解可能会相对吃力。

一. 准备工作

1. 创建必要文件 

本次通讯录项目基于上次我们顺序表的实现,所以需要使用到上次我们编写的文件:SeqList.h,SeqList.c,test.c

同时我们还需要创建本次通讯录项目的代码文件:Contact.h,Contact.c

现在,我们手中已经有了五个代码文件,现在我们来整理一下,确定这些代码文件的具体作用:

代码文件具体作用
代码文件作用

SeqList.h

顺序表的函数声明
SeqList.c顺序表的函数实现
Contact.h通讯录的代码声明
Contact.c通讯录的函数实现
test.c主函数和菜单

现在,我们明确了各个代码文件的具体作用,这些文件又应该如何包含起来,联系到一起呢?

2. 确定文件包含关系 

下面是本次通讯录项目中各个代码文件包含关系图: 

代码文件之间的包含关系示意图
为什么这么包含呢?我们下面结合具体代码解释。

 3. 设计通讯录结构体

我们将包含联系人信息的结构体命名为PersonInfo,包含了联系人的姓名name,性别gender,年龄age,电话号码tel,地址addr。

#define NAME_MAX 20
#define GENDER_MAX 10
#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;

 同样的,为了方便代码书写,我们将结构体进行重命名,同时,为了方便以后我们更改字符串长度,我们使用了#define的方式来确定字符串长度。

注意:由于涉及字符串的处理,需要加上<string.h> 。

既然我们已经确定了联系人信息的结构体,那么我们之前在Seqlist.h中的临时将int类型重命名为SLDataType就不合适了,应该将PersonInfo类型重命名为SLDataType。

//将通讯录结构体类型重命名为SLDataType
typedef PeoInfo SLDataType;

这里就体现出了我们之前编写时对数据类型进行重命名的优势,方便了此处对其进行修改。 

4. 重命名顺序表为通讯录

既然我们是一个通讯录项目,那么叫做SeqList也不合适了,我们将其重命名为通讯录Contact

//对结构体SL进行重命名为Contact
//因为没有不会SL的头文件,使用声明+typedef
typedef struct SeqList Contact;

5. 对通讯录结构的理解 

通讯录结构体: 

Contact
数据类型名字

SLDataType*

arr

int

size
intcapacity

联系人结构体:

PersonInfo
数据类型名字/数组名数组长度
charnameNAME_MAX
chargenderGENDER_MAX
intage\
chartelTEL_MAX
charaddrADDR_MAX

通讯录结构体的理解

这里将PersonInfo设置为SLDataType

通讯录结构体的理解

二. 函数实现

1. 初始化 ContactInit

函数原型式:

void ContactInit(Contact* con);

代码实现:

//通讯录的初始化
void ContactInit(Contact* con)
{
	//con就是SL
	SLInit(con);
}

由于Contact是由SL重命名而成,所以可以直接调用SL的初始化函数。

2. 销毁 ContactDestroy

  函数原型式:

void ContactDestroy(Contact* con);

代码实现:

//通讯录的销毁
void ContactDestroy(Contact* con)
{
	//SaveContact(con);//在销毁退出前保存数据
	SLDestroy(con);
}

代码解释同上,这里不加赘述。

3. 添加数据 ContactAdd

函数原型式:

void ContactAdd(Contact* con);

代码实现:

//通讯录添加数据
void ContactAdd(Contact* con)
{
	//获取用户输入的内容
	//姓名+性别+年龄+电话+地址
	PeoInfo info;
	printf("请输入联系人姓名:");
	scanf("%s", info.name);
	printf("请输入联系人性别:");
	scanf("%s", info.gender);
	printf("请输入联系人年龄:");
	scanf("%d", &info.age);
	printf("请输入联系人电话:");
	scanf("%s", info.tel);
	printf("请输入联系人地址:");
	scanf("%s", info.addr);

	//往通讯录中添加联系人数据
	SLPushBack(con, info);
}

我们先创建一个联系人结构体,然后对其输入数据,最后将其尾插到数组的结尾。

4. 按姓名查找 FindByName

函数原型式:

int FindByName(Contact* con, char name[]);

代码实现

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;
}

 这里实现一个按照姓名查找数据,由于我们的顺序表的数据存储是数组结构,就相当于一个在数组中查找元素,如果找到了,就返回元素下标,如果没找到,就返回EOF(-1)

如果你需要按其它方式查找,也可以写出相应的代码。

5. 删除数据 ContactDel

函数原型式:

void ContactDel(Contact* con);

代码实现:

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

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	else
	{
		//找到了该联系人数据,找到了下标 —— 删除指定位置的数据
		SLErase(con, find);
		printf("删除成功!\n");
	}
}

想要删除一个数据,就要先找到这一条数据,找不到,就提示不存在返回,找到了,就调用顺序表的尾删。

6. 修改 ContactModify

函数原型式:

void ContactModify(Contact* con);

代码实现:

//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的联系人数据存在
	char name[NAME_MAX] = { 0 };
	printf("请输入要修改的联系人姓名:");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("联系人数据不存在!\n");
		return;
	}
	else
	{
		printf("请输入联系人新的姓名:");
		scanf("%s", con->arr[find].name);
		printf("请输入联系人新的性别:");
		scanf("%s", con->arr[find].gender);
		printf("请输入联系人新的年龄:");
		scanf("%d", &(con->arr[find].age));
		printf("请输入联系人新的电话:");
		scanf("%s", con->arr[find].tel);
		printf("请输入联系人新的地址:");
		scanf("%s", con->arr[find].addr);
		printf("修改成功!\n");
	}
}

要修改数据同样也需要查找到这一条数据,找不到,就提示不存在返回,找到了,就直接修改数组中对应的数据。

7. 查找 ContactFind

函数原型式:

void ContactFind(Contact* con);

代码实现:

//通讯录的查找
void ContactFind(Contact* con)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要查找的联系人姓名:");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("联系人数据不存在!\n");
		return;
	}
	else
	{
		//表头: 姓名 性别 年龄 电话 地址
		printf("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
		printf("%5s %5s %5d %10s %5s\n", \
			con->arr[find].name, \
			con->arr[find].gender, \
			con->arr[find].age, \
			con->arr[find].tel, \
			con->arr[find].addr);
	}
}

要查找数据同样也需要先查找到这一条数据,找不到,就提示不存在返回,找到了,就展示这一条数据。

8. 展示数据ContactShow

函数原型式:

void ContactShow(Contact* con);

代码实现:

//展示通讯录数据
void ContactShow(Contact* con)
{
	//表头: 姓名 性别 年龄 电话 地址
	printf("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%5s %5s %5d %10s %5s\n", \
			con->arr[i].name, \
			con->arr[i].gender, \
			con->arr[i].age, \
			con->arr[i].tel, \
			con->arr[i].addr);
	}
}

这里展示数据就是遍历数组中的所有元素,然后将每一条数据打印出来。

9. 保存数据 SaveContact

 下面的保存和读取数据涉及文件操作的相关知识。

函数原型式:

void SaveContact(Contact* con);

代码实现:

//保存通讯录数据
void SaveContact(Contact* con)
{
	FILE* pf = NULL;
	pf = fopen("Contact.dat", "w");
	if (pf == NULL)
	{
		perror("Failed to write to file");
		return;
	}
	//写入数据
	fprintf(pf, "%d\n", con->size);//写入有效数据个数
	for (int i = 0; i < con->size; i++)//写入通讯录数据
	{
		fprintf(pf, "%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);
	}
	printf("数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}

这里先写入有效的元素个数,在一行一行地写入具体的联系人数据。

为什么要写入有效元素个数呢,直接写入数据不就可以了吗?

也可以,但如果程序退出,再次进入时会初始化通讯录,那么有效元素个数将为0,如果不写入有效元素个数,就需要在读取时计数,判断读取了多少条数据,并相应的进行扩容等操作。

10. 读取数据 ReadContact

函数原型式:

void ReadContact(Contact* con);

代码实现:

//读取通讯录数据
void ReadContact(Contact* con)
{
	FILE* pf = NULL;
	pf = fopen("Contact.dat", "r");
	if (pf == NULL)
	{
		perror("Failed to read to file");
		return;
	}
	fscanf(pf, "%d", &(con->size));//读取有效数据个数
	for (int i = 0; i < con->size; i++)
	{
		PeoInfo info = { 0 };
		fscanf(pf, "\n%s %s %d %s %s", \
			info.name, \
			info.gender, \
			& (info.age), \
			info.tel, \
			info.addr);
		//SLPushBack(con, info);//不能使用尾插
		SLCheckCapacity(con);//容量判断
		con->arr[i] = info;
	}
	printf("数据读取成功!\n");
	fclose(pf);
	pf = NULL;
}

上面我们写入了有效元素个数,我们在下面就只需要读取,然后判断是否需要扩容,最后插入数据。

注意:由于我们先读取有效个数,可能会导致刚读取时有效数据个数大于元素个数的情况,因此需要对SeqList.c中的SLCheckCapacity函数进行修改,否则无法正常扩容。

if (ps->size >= ps->capacity)//为通讯录读取增容创造条件

如果需要在已有的数据后面添加从文件中读取的数据,只需要从有效元素个数后面开始尾插即可。

11. 增容 SLCheckCapacity

 此处放置增容函数的声明仅仅是因为之前的函数声明为SL,而现在我们已经重命名为Contact,使用以前的函数声明会报错。

void SLCheckCapacity(Contact* con);

12. 菜单 menu

void menu(void)
{
	printf("***************通讯录****************\n");
	printf("*                                   *\n");
	printf("*           1.增加联系人            *\n");
	printf("*           2.删除联系人            *\n");
	printf("*           3.修改联系人            *\n");
	printf("*           4.查找联系人            *\n");
	printf("*           5.展示联系人            *\n");
	printf("*           6.读取联系人            *\n");
	printf("*           7.保存联系人            *\n");
	printf("*              0.退出               *\n");
	printf("*                                   *\n");
	printf("*************************************\n");
}

菜单仅仅需要逐行打印即可。

13. 主函数 main

int main()
{
	int input = 0;
	Contact con;
	ContactInit(&con);
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		//选择
		switch (input)
		{
		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 6:
			ReadContact(&con);
			break;
		case 7:
			SaveContact(&con);
			break;
		case 0:
			printf("退出通讯录……\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
	ContactDestroy(&con);
	return 0;
}

创建一个通讯录结构体并初始化,然后使用do-while循环和switch…case语句选择,然后调用相应的函数,最后销毁,空间释放,函数返回,程序结束。

三. 参考代码

Contact.h

#pragma once

#define NAME_MAX 20
#define GENDER_MAX 10
#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;

//对结构体SL进行重命名为Contact
//因为没有包含SL的头文件,使用声明+typedef
typedef struct SeqList Contact;

//struct SeqList;//声明结构体
//typedef SL Contact;//给结构体改名

//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录的查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);
//保存通讯录数据
void SaveContact(Contact* con);
//读取通讯录数据
void ReadContact(Contact* con);
//顺序表的增容
void SLCheckCapacity(Contact* con);

Contact.c

#include "Contact.h"
#include "SeqList.h"
#include <string.h>

//通讯录的初始化
void ContactInit(Contact* con)
{
	//con就是SL
	SLInit(con);
}

//通讯录的销毁
void ContactDestroy(Contact* con)
{
	//SaveContact(con);//在销毁退出前保存数据
	SLDestroy(con);
}

//通讯录添加数据
void ContactAdd(Contact* con)
{
	//获取用户输入的内容
	//姓名+性别+年龄+电话+地址
	PeoInfo info;
	printf("请输入联系人姓名:");
	scanf("%s", info.name);
	printf("请输入联系人性别:");
	scanf("%s", info.gender);
	printf("请输入联系人年龄:");
	scanf("%d", &info.age);
	printf("请输入联系人电话:");
	scanf("%s", info.tel);
	printf("请输入联系人地址:");
	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] = { 0 };
	printf("请输入要删除的联系人姓名:");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	else
	{
		//找到了该联系人数据,找到了下标 —— 删除指定位置的数据
		SLErase(con, find);
		printf("删除成功!\n");
	}
}

//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的联系人数据存在
	char name[NAME_MAX] = { 0 };
	printf("请输入要修改的联系人姓名:");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("联系人数据不存在!\n");
		return;
	}
	else
	{
		printf("请输入联系人新的姓名:");
		scanf("%s", con->arr[find].name);
		printf("请输入联系人新的性别:");
		scanf("%s", con->arr[find].gender);
		printf("请输入联系人新的年龄:");
		scanf("%d", &(con->arr[find].age));
		printf("请输入联系人新的电话:");
		scanf("%s", con->arr[find].tel);
		printf("请输入联系人新的地址:");
		scanf("%s", con->arr[find].addr);
		printf("修改成功!\n");
	}
}

//通讯录的查找
void ContactFind(Contact* con)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要查找的联系人姓名:");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("联系人数据不存在!\n");
		return;
	}
	else
	{
		//表头: 姓名 性别 年龄 电话 地址
		printf("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
		printf("%5s %5s %5d %10s %5s\n", \
			con->arr[find].name, \
			con->arr[find].gender, \
			con->arr[find].age, \
			con->arr[find].tel, \
			con->arr[find].addr);
	}
}

//展示通讯录数据
void ContactShow(Contact* con)
{
	//表头: 姓名 性别 年龄 电话 地址
	printf("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%5s %5s %5d %10s %5s\n", \
			con->arr[i].name, \
			con->arr[i].gender, \
			con->arr[i].age, \
			con->arr[i].tel, \
			con->arr[i].addr);
	}
}

//保存通讯录数据
void SaveContact(Contact* con)
{
	FILE* pf = NULL;
	pf = fopen("Contact.dat", "w");
	if (pf == NULL)
	{
		perror("Failed to write to file");
		return;
	}
	//写入数据
	fprintf(pf, "%d\n", con->size);//写入有效数据个数
	for (int i = 0; i < con->size; i++)//写入通讯录数据
	{
		fprintf(pf, "%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);
	}
	printf("数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}

//读取通讯录数据
void ReadContact(Contact* con)
{
	FILE* pf = NULL;
	pf = fopen("Contact.dat", "r");
	if (pf == NULL)
	{
		perror("Failed to read to file");
		return;
	}
	fscanf(pf, "%d", &(con->size));//读取有效数据个数
	for (int i = 0; i < con->size; i++)
	{
		PeoInfo info = { 0 };
		fscanf(pf, "\n%s %s %d %s %s", \
			info.name, \
			info.gender, \
			& (info.age), \
			info.tel, \
			info.addr);
		//SLPushBack(con, info);//不能使用尾插
		SLCheckCapacity(con);//容量判断
		con->arr[i] = info;
	}
	printf("数据读取成功!\n");
	fclose(pf);
	pf = NULL;
}

SeqList.h

 #pragma once

#define _CRT_SECURE_NO_WARNINGS 1

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

//typedef int SLDataType;

//将通讯录结构体类型重命名为SLDataType
typedef PeoInfo SLDataType;

//动态顺序表
//将结构体SeqList重命名为SL
typedef struct SeqList
{
	SLDataType* arr;
	int size;
	int capacity;
}SL;

//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
//头部插入数据
void SLPushFront(SL* ps, SLDataType x);
//尾部插入数据
void SLPushBack(SL* ps, SLDataType x);
//打印顺序表
void SLPrint(SL s);
//头部删除数据
void SLPopFront(SL* ps);
//尾部删除数据
void SLPopBack(SL* ps);
//任意位置前插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
//任意位置删除数据
void SLErase(SL* ps, int pos);
//顺序表的查找
//int SLFind(SL* ps, SLDataType x);

SeqList.c

#include "SeqList.h"

void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

void SLDestroy(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

void SLCheckCapacity(SL* ps)
{
	//在插入数据前先判断空间够不够
	if (ps->size >= ps->capacity)//为通讯录读取增容创造条件
	{
		//申请空间 -- 增容 --> realloc
		//增容一般是两倍或者三倍的增加,过大或者过小,频繁的增容,会使程序的运行效率降低
		//注意:判断capacity是否为0
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
}

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	在插入数据前先判断空间够不够
	//if (ps->size == ps->capacity)
	//{
	//	//申请空间 -- 增容 --> realloc
	//	//增容一般是两倍或者三倍的增加,过大或者过小,频繁的增容,会使程序的运行效率降低
	//	//注意:判断capacity是否为0
	//	int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
	//	SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
	//	if (tmp == NULL)
	//	{
	//		perror("realloc failed");
	//		exit(1);
	//	}
	//	ps->arr = tmp;
	//	ps->capacity = newcapacity;
	//}

	SLCheckCapacity(ps);

	//尾插
	ps->arr[ps->size++] = x;
	//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++;
}

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

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	//ps->arr[ps->size - 1] = -1;
	--(ps->size);
}

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	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);

	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;
//}

test.c

#include "SeqList.h"

//void SLtest(void)
//{
//	SL sl;
//	SLInit(&sl);
//	
//	for (int i = 0; i < 10; i++)
//	{
//		SLPushBack(&sl, i);
//		SLPrint(sl);
//	}
//
//	for (int i = 0; i < 10; i++)
//	{
//		SLPushFront(&sl, i);
//		SLPrint(sl);
//	}
//
//	SLPopFront(&sl);
//	SLPrint(sl);
//
//	SLPopBack(&sl);
//	SLPrint(sl);
//
//	SLDestroy(&sl);
//}

//void SLtest2()
//{
//	SL sl;
//	SLInit(&sl);
//
//	for (int i = 0; i < 10; i++)
//	{
//		SLPushBack(&sl, i);
//	}
//	SLPrint(sl);
//
//	SLErase(&sl, 0);
//	SLPrint(sl);
//
//	SLInsert(&sl, 1, 10);
//	SLPrint(sl);
//
//	int ret = 0;
//	ret = SLFind(&sl, 5);
//	printf("ret=%d\n", ret);
//
//	ret = SLFind(&sl, 11);
//	printf("ret=%d\n", ret);
//
//	SLDestroy(&sl);
//}

//void ContactTest01()
//{
//	Contact con;//创建的通讯录对象,实际上就是顺序表对象
//	ContactInit(&con);//通讯录的初始化
//
//	ContactAdd(&con);//添加数据
//	ContactAdd(&con);
//	ContactShow(&con);
//
//	//ContactDel(&con);
//	//ContactShow(&con);
//
//	//ContactModify(&con);
//	//ContactShow(&con);
//
//	ContactFind(&con);
//
//	ContactDestroy(&con);//通讯录的销毁
//}

//int main()
//{
//	//顺序表的测试
//	//SLtest();
//	//SLtest2();
//
//	//通讯录的测试
//	ContactTest01();
//
//	return 0;
//}

void menu(void)
{
	printf("***************通讯录****************\n");
	printf("*                                   *\n");
	printf("*           1.增加联系人            *\n");
	printf("*           2.删除联系人            *\n");
	printf("*           3.修改联系人            *\n");
	printf("*           4.查找联系人            *\n");
	printf("*           5.展示联系人            *\n");
	printf("*           6.读取联系人            *\n");
	printf("*           7.保存联系人            *\n");
	printf("*              0.退出               *\n");
	printf("*                                   *\n");
	printf("*************************************\n");
}

int main()
{
	int input = 0;
	Contact con;
	ContactInit(&con);
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		//选择
		switch (input)
		{
		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 6:
			ReadContact(&con);
			break;
		case 7:
			SaveContact(&con);
			break;
		case 0:
			printf("退出通讯录……\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
	ContactDestroy(&con);
	return 0;
}

写在最后

本次我们实现了基于动态顺序表的通讯录项目,实现了通讯录的增删查改等操作 ,并添加了相关的文件操作的功能,加深了我们对于顺序表这一数据结构的了解。

本次展示的代码仅仅是对项目相关函数功能的简单实现,不建议大家直接copy,实现的通讯录也绝非完美,你可以对代码进行增添、修改等操作使其变得更完美,比如在初始化后直接从文件中读取数据,在程序退出前自动将数据保存到文件中等等……

Believe in yourself!

  • 13
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值