通讯录的实现思路和详细解析(C语言版本)

目录

0.前言

1.写通讯录的准备工作

1.1 通讯录结构的准备

1.2 通讯录功能的准备

1.3 通讯录菜单的准备

(1)在屏幕中输出一个菜单

(2)菜单选项的表示

 (3)菜单功能的实现

2.通讯录功能的实现

2.0 通讯录的初始化操作

 2.1 添加联系人信息

 2.2. 删除联系人信息

2.3  查找指定联系人(这里以查询联系人的姓名为例)

2.4. 修改指定联系人的信息

2.5 将已添加联系人的信息进行排序(这里以联系人名字的首字母为例)

2.6 展示通讯录的信息

 2.7 销毁通讯录

 2.8 退出通讯录

3.完整代码整合

3.1 头文件 contact.h

3.2  通讯录功能实现函数 contact.c

 3.3 主函数 main.c

4 .调试技巧及注意事项

4.1 调试技巧

4.2注意事项

5.结语


0.前言

  学到这里相信你已经有了一定的c语言基础,这个案例中我们学习的c语言的大部分知识都会有所体现,借此机会来检验一下你是否能将你所学的c语言实际运用起来吧! 

1.写通讯录的准备工作

1.1 通讯录结构的准备

   作为一个基本通讯录的实现,我们要创建一个联系人结构体,在这个结构体要包含联系人的基本信息。如下代码所示,为了方便代码的修改,在这里宏定义了一些数组的大小。

#define NAME_MAX 20
#define PHONE_MAX 12
#define SEX_MAX 5
#define ADDRESS_MAX 30

//联系人结构体
typedef struct PeoInfo
{
	//联系人姓名
	char name[NAME_MAX];
	//联系人手机号
	char phone[PHONE_MAX];
	//联系人年龄
	int age;
	//联系人性别
	char sex[SEX_MAX];
	//联系人地址
	char address[ADDRESS_MAX];
	
}PeoInfo;

  我们现在已经有了联系人的存储方法了,接下来我们需要一个结构体来表示整个通讯录,这个通讯录需要存储每个联系人,所以要有一个联系人数组,为了节省空间和方便后续联系人数组的扩展,我们将用指针来指向联系人数组,通过动态开辟内存空间来实现这个联系人数组。最后再在通讯录这个结构体中加入变量size来表示当前联系人的数量,用capacity来表示动态内存开辟空间的最大容量(方便后序空间的扩展),代码如下:

typedef struct Contact
{
	//联系人数组(指针创建方便动态开辟内存空间)
	PeoInfo* data;
	//通讯录当前容量
	int size;
	//通讯录容量(用于检测是否需要开辟空间)
	int capacity;
}Contact;

1.2 通讯录功能的准备

  在开始敲代码之前我们先想想通讯录必备的功能都有些什么 以便于我们写代码时能有一个更清晰的思路。现在我们来结合手机中的通讯录来列举一些通讯录中最基本的一些功能。

        0.菜单栏(便于用户操作,使用通讯录的各种功能) 

        1.添加联系人信息

        2. 删除联系人信息

        3.查找指定联系人(这里以查询联系人的姓名为例)

        4.修改指定联系人的信息

        5.将已添加联系人的信息进行排序(这里以联系人名字的首字母为例)

        6.展示通讯录的信息

        7.销毁通讯录

        8.退出通讯录

  以上功能便是一个通讯录的基本功能了,具体功能实现将在下文一一列举,也欢迎大家来扩充更多的功能来实现一个更完美的通讯录。

在头文件中完成通讯录功能的初步准备:

//初始化通讯录
void InitConctact(Contact* pc);
//1.添加联系人信息
void AddContact(Contact* pc);
//2. 删除联系人信息
void DelContact(Contact* pc);
//3.查找指定联系人(这里以查询联系人的姓名为例)
void SearchContact(Contact* pc);
//4.修改指定联系人的信息
void ModifyContact(Contact* pc);
//5.将已添加联系人的信息进行排序(这里以联系人名字的首字母为例)
void SortContact(Contact* pc);
//6.展示通讯录的信息
void ShowContact(Contact* pc);
//7.销毁通讯录
void DestortContact(Contact* pc);
//8.退出通讯录
void ExitContact(Contact* pc);

1.3 通讯录菜单的准备

(1)在屏幕中输出一个菜单

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

(2)菜单选项的表示

为了使代码中菜单的选项更加直观的表示,我们这里运用枚举来表示菜单的各个选项,这样可增强代码的可读性

//菜单选项
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
	
};

 (3)菜单功能的实现

前面的准备工作已经完成,接下来我们要将其整合并加入通讯录的功能来实现菜单。(现将菜单的功能准备出来,在后续逐一实现)

//菜单选项
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
	
};
//菜单
void menu()
{
	printf("*****************************************\n");
	printf("**** 1. 添加联系人     2. 删除联系人 ****\n");
	printf("**** 3. 查找联系人     4. 修改联系人 ****\n");
	printf("**** 5. 展示通讯录     6. 联系人排序 ****\n");
	printf("**** 0. 退出程序                     ****\n");
	printf("*****************************************\n");
}

int main()
{
	//创建通讯录
	Contact contact;
	//初始化通讯录
	InitConctact(&contact);
	do
	{
		menu();

		int choice = 0;
		scanf("%d", &choice);
		
		switch (choice)
		{
		case ADD:
			AddContact(&contact);
			break;
		case DEL:
			DelContact(&contact);
			break;
		case SEARCH:
			SearchContact(&contact);
			break;
		case MODIFY:
			ModifyContact(&contact);
			break;
		case SHOW:
			ShowContact(&contact);
			break;
		case SORT:
			SortContact(&contact);
			break;
		case EXIT:
			ExitContact(&contact);
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
		system("pause");
		system("cls");

	} while (1);
	return 0;
}

2.通讯录功能的实现

2.0 通讯录的初始化操作

初始化中我们要先将通讯录的联系人数组开辟初始化设置好的空间,并将数组容量设置为我们开始想要开辟的空间大小,最后将当前联系人数量置为0.

//联系人的初始大小
#define DEFAULT_SET 3

//初始化通讯录
void InitConctact(Contact* pc)
{
	assert(pc);
	//开辟联系人数组
	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SET);
	if (pc->data == NULL)
	{
		perror("InitContact->malloc");
		return;
	}
	pc->size = 0;
	pc->capacity = DEFAULT_SET;
}

 2.1 添加联系人信息

在本讲解中的初始化中我们是动态开辟的联系人数组。所以在添加联系人时,我们需要考虑数组空间是否充足。如果不足的话需要用realloc来开辟内存空间。

下面的代码为检查内存空间是否充足:

//检查空间是否需要开辟空间
void CheckCapacity(Contact* pc)
{
	assert(pc);
	//如果空间满了则开辟空间
	if (pc->size == pc->capacity)
	{
		//标记数组新容量
		int newcapacity = (pc->capacity) + DEFAULT_INC;
		//增容
		PeoInfo* newspace = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * newcapacity);

		if (newspace == NULL)
		{
			perror("CheckCapacity->realloc");
			return;
		}
		pc->data = newspace;
		pc->capacity = newcapacity;
		printf("增容成功\n");
	}
}

 为了方便观察数组是否增容,在增容完成后输出了一个 增容成功 ,这样方便我们更好的理解数组在什么时候增容的。(在最后完成全部代码后可删除)。

   接下来将正式进行添加联系人操作,添加联系人要先检查是否需要增容,然后只需要将联系人信息按序输入到联系人数组中。添加完成后最后将数组容量加1.

 注:在添加完成后再使数组容量size+1是因为数组下标从0开始,为了准确将信息按序放入

代码如下:

void AddContact(Contact* pc)
{
	assert(pc);

	//增加容量
	CheckCapacity(pc);
	//增加信息
	printf("请输入名字:");
	scanf("%s", pc->data[pc->size].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->size].age));
	printf("请输入性别:");
	scanf("%s", pc->data[pc->size].sex);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->size].phone);
	printf("请输入地址:");
	scanf("%s", pc->data[pc->size].address);

	printf(" %s 添加成功\n", pc->data[pc->size].name);

	(pc->size)++;
}

添加联系人完整代码如下: 

//1.添加联系人信息
//检查空间是否需要开辟空间
void CheckCapacity(Contact* pc)
{
	assert(pc);
	//如果空间满了则开辟空间
	if (pc->size == pc->capacity)
	{
		//标记数组新容量
		int newcapacity = (pc->capacity) + DEFAULT_INC;
		//增容
		PeoInfo* newspace = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * newcapacity);

		if (newspace == NULL)
		{
			perror("CheckCapacity->realloc");
			return;
		}
		pc->data = newspace;
		pc->capacity = newcapacity;
		printf("增容成功\n");
	}
}
void AddContact(Contact* pc)
{
	assert(pc);

	//增加容量
	CheckCapacity(pc);
	//增加信息
	printf("请输入名字:");
	scanf("%s", pc->data[pc->size].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->size].age));
	printf("请输入性别:");
	scanf("%s", pc->data[pc->size].sex);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->size].phone);
	printf("请输入地址:");
	scanf("%s", pc->data[pc->size].address);

	printf(" %s 添加成功\n", pc->data[pc->size].name);

	(pc->size)++;

 2.2. 删除联系人信息

  这里删除联系人为删除指定名字的联系人,如果存在重名的情况优先删除排序靠前的联系人。

    我们删除指定名字的联系人,首先需要的是查找指定联系人是否存在,因为后续功能的实现也需要查找指定联系人,所以我们将查找指定名字联系人是否存在这一功能单独写出。

为了方便后序功能的实现,查找函数的返回值类型为int,这样一来方便返回联系人所在位置的下标。

查找联系人时是否存在代码如下:

//查看联系人是否存在(依据名字)
int ExistContact(Contact* pc, char name[])
{
	assert(pc);
    
    //查找联系人是否存在,存在则返回联系人数组下标,若不存在则返回-1
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}

  然后我们来看如何删除对应位置的联系人。

   存放联系人的数组相当于是一个顺序表(简单的说联系人数组中每个联系人都在联系人数组中按顺序存储),所以我们不能仅仅只删除对应位置的联系人,因为这样会破坏顺序表的结构,破坏了数据的连续性,不便于我们后序的操作。

  所以为了不破坏数据的连续性,我们要从删除数据的后一个位置的数据开始,将数据一个一个的覆盖到前一个数据的位置,这样既可以删除对应位置的数据,又能保证数据的连续性。

   那新的问题又来了,原数组最后一个数据没有变化,那该怎么办呢?

这里只需要将联系人数组的当前空间 size 减1即可,这样最后一个数据就不会被访问到,如果要添加新数据的话,也可以将老数据直接覆盖掉。

        删除联系人信息代码如下:

//删除联系人
void DelContact(Contact* pc)
{
	assert(pc);
    
    printf("请输入删除的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	//判断联系人是否存在
	int ret = ExistContact(pc, name);
	//联系人存在则ret大于等于0,删除联系人
	if (ret>=0)
	{
		for (int i = ret; i < pc->size-1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		(pc->size)--;

		printf("成功删除 %s \n", name);
	}
	else
	{
		printf("通讯录中未找到 %s \n", name);
	}
	
}

 删除联系人完整代码如下:

//2. 删除联系人信息

//查看联系人是否存在(依据名字)
int ExistContact(Contact* pc, char name[])
{
	assert(pc);

	//查找联系人是否存在,存在则返回联系人数组下标,若不存在则返回-1
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}
//删除联系人
void DelContact(Contact* pc)
{
	assert(pc);

	printf("请输入删除的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	//判断联系人是否存在
	int ret = ExistContact(pc, name);
	//联系人存在则ret大于等于0,删除联系人
	if (ret>=0)
	{
		for (int i = ret; i < pc->size-1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		(pc->size)--;

		printf("成功删除 %s \n", name);
	}
	else
	{
		printf("通讯录中未找到 %s \n", name);
	}
	
}

2.3  查找指定联系人(这里以查询联系人的姓名为例)

  在完成了上述查找联系人是否存在的函数后,查找联系人只需查找对应联系人是否存在,如果存在输出联系人信息即可。

代码如下:

//查看联系人是否存在(依据名字)
int ExistContact(Contact* pc, char name[])
{
	assert(pc);

    //查找联系人是否存在,存在则返回联系人数组下标,若不存在则返回-1
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}

//3.查找指定联系人(这里以查询联系人的姓名为例)
void SearchContact(Contact* pc)
{
    assert(pc);

	printf("请输入查找的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	//查找联系人是否存在,存在则ret大于等于0
	int ret = ExistContact(pc, name);
	if (ret >= 0)
	{
		printf("%-8s%-12s%-17s%-8s%-8s%-8s\n", "序号", "姓名", "手机号", "年龄", "性别", "地址");
		printf("%-8d%-12s%-17s%-8d%-8s%-8s\n",
			ret+1, pc->data[ret].name, pc->data[ret].phone, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].address);
	}
	else
	printf("未找到 %s \n", name);
}

2.4. 修改指定联系人的信息

在完成了上述查找联系人是否存在的函数后,查找联系人只需查找对应联系人是否存在,如果存在则在对应位置重新输入信息即可。

具体代码如下:

//查看联系人是否存在(依据名字)
int ExistContact(Contact* pc, char name[])
{    
    assert(pc);	

    //查找联系人是否存在,存在则返回联系人数组下标,若不存在则返回-1
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}


//4.修改指定联系人的信息
void ModifyContact(Contact* pc)
{
	assert(pc);

    printf("请输入需要修改的联系人:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	//标记所需修改的联系人的数组下标
	int ret = ExistContact(pc, name);

	//联系人存在则修改
	if (ret >= 0)
	{
		printf("请输入名字:");
		scanf("%s", pc->data[ret].name);
		printf("请输入年龄:");
		scanf("%d", &(pc->data[ret].age));
		printf("请输入性别:");
		scanf("%s", pc->data[ret].sex);
		printf("请输入电话:");
		scanf("%s", pc->data[ret].phone);
		printf("请输入地址:");
		scanf("%s", pc->data[ret].address);

		printf(" %s 添加成功\n", pc->data[ret].name);
	}
	else
	{
		printf("联系人输入有误\n");
	}
}

2.5 将已添加联系人的信息进行排序(这里以联系人名字的首字母为例)

一般通讯录都是根据名字的首字母排序,所以这里我们运用快排直接对联系人的名字进行排序即可。

如果对快速排序不了解的朋友可以看我的另外两篇博客:

快速排序详解:qsort(快速排序)使用详解!!!(开启刷题大门的第一步)-CSDN博客

快速上手快速排序:0基础刷题必备,有了它便可打开你的刷题之路!(c语言)-CSDN博客

具体代码如下:

//5.将已添加联系人的信息进行排序(这里以联系人名字的首字母为例)
int cmp_stu_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	assert(pc);

	qsort(pc->data, pc->size, sizeof(pc->data[pc->size]),cmp_stu_name);
}

2.6 展示通讯录的信息

为了展示效果的美观,这里我们要在输出时运用到输出的左对齐(左对齐就是要在打印数字宽度前面加一个“-”。)

代码实例如下:

//6.展示通讯录的信息
void ShowContact(Contact* pc)
{
	printf("%-8s%-12s%-17s%-8s%-8s%-8s\n", 
             "序号", "姓名","手机号","年龄","性别","地址");
	for (int i = 0; i < pc->size; i++)
	{
		printf("%-8d%-12s%-17s%-8d%-8s%-8s\n",
			i+1, pc->data[i].name, pc->data[i].phone, 
            pc->data[i].age, pc->data[i].sex,pc->data[i].address);
	}
}

 2.7 销毁通讯录

在退出程序时,为了防止内存泄漏和野指针的出现,我们需要加入一个销毁通讯录的功能。

先释放开辟的内存,再将对应位置置空,最后将联系人数量和通讯录容量置为0,完成通讯录的销毁功能。

具体代码如下:

//7.销毁通讯录
void DestortContact(Contact* pc)
{
	assert(pc);

	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;
}

 2.8 退出通讯录

如上述销毁通讯录操作所讲,在退出通讯录前需要先销毁通讯录。

退出通讯操作即需要 先将通讯录销毁之后进行程序的退出操作

具体代码如下:

//销毁通讯录
void DestortContact(Contact* pc)
{
	assert(pc);

	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;
}

//8.退出通讯录
void ExitContact(Contact*pc)
{
	assert(pc);

	DestortContact(pc);
	printf("欢迎您下次使用\n");

	exit(-1);
}

3.完整代码整合

3.1 头文件 contact.h

#pragma once
#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<Windows.h>

#define NAME_MAX 20
#define PHONE_MAX 12
#define SEX_MAX 5
#define ADDRESS_MAX 30
//联系人的初始大小
#define DEFAULT_SET 3
//联系人每次扩容的大小
#define DEFAULT_INC 2

//联系人结构体
typedef struct PeoInfo
{
	//联系人姓名
	char name[NAME_MAX];
	//联系人手机号
	char phone[PHONE_MAX];
	//联系人年龄
	int age;
	//联系人性别
	char sex[SEX_MAX];
	//联系人地址
	char address[ADDRESS_MAX];
	
}PeoInfo;

typedef struct Contact
{
	//联系人数组(指针创建方便动态开辟内存空间)
	PeoInfo* data;
	//通讯录当前容量
	int size;
	//通讯录容量(用于检测是否需要开辟空间)
	int capacity;
}Contact;
//初始化通讯录
void InitConctact(Contact* pc);
//1.添加联系人信息
void AddContact(Contact* pc);
//2. 删除联系人信息
void DelContact(Contact* pc);
//3.查找指定联系人(这里以查询联系人的姓名为例)
void SearchContact(Contact* pc);
//4.修改指定联系人的信息
void ModifyContact(Contact* pc);
//5.将已添加联系人的信息进行排序(这里以联系人名字的首字母为例)
void SortContact(Contact* pc);
//6.展示通讯录的信息
void ShowContact(Contact* pc);
//7.销毁通讯录
void DestortContact(Contact* pc);
//8.退出通讯录
void ExitContact(Contact* pc);

3.2  通讯录功能实现函数 contact.c

#include"contact.h"

//初始化通讯录
void InitConctact(Contact* pc)
{
	assert(pc);

	//开辟联系人数组
	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SET);
	if (pc->data == NULL)
	{
		perror("InitContact->malloc");
		return;
	}
	pc->size = 0;
	pc->capacity = DEFAULT_SET;
}
//1.添加联系人信息
//检查空间是否需要开辟空间
void CheckCapacity(Contact* pc)
{
	assert(pc);

	//如果空间满了则开辟空间
	if (pc->size == pc->capacity)
	{
		//标记数组新容量
		int newcapacity = (pc->capacity) + DEFAULT_INC;
		//增容
		PeoInfo* newspace = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * newcapacity);

		if (newspace == NULL)
		{
			perror("CheckCapacity->realloc");
			return;
		}
		pc->data = newspace;
		pc->capacity = newcapacity;
		printf("增容成功\n");
	}
}
void AddContact(Contact* pc)
{
	assert(pc);

	//增加容量
	CheckCapacity(pc);
	//增加信息
	printf("请输入名字:");
	scanf("%s", pc->data[pc->size].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->size].age));
	printf("请输入性别:");
	scanf("%s", pc->data[pc->size].sex);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->size].phone);
	printf("请输入地址:");
	scanf("%s", pc->data[pc->size].address);

	printf(" %s 添加成功\n", pc->data[pc->size].name);

	(pc->size)++;
}
//2. 删除联系人信息

//查看联系人是否存在(依据名字)
int ExistContact(Contact* pc, char name[])
{
	assert(pc);

	//查找联系人是否存在,存在则返回联系人数组下标,若不存在则返回-1
	for (int i = 0; i < pc->size; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}
//删除联系人
void DelContact(Contact* pc)
{
	assert(pc);

	printf("请输入删除的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	//判断联系人是否存在
	int ret = ExistContact(pc, name);
	//联系人存在则ret大于等于0,删除联系人
	if (ret>=0)
	{
		for (int i = ret; i < pc->size-1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		(pc->size)--;

		printf("成功删除 %s \n", name);
	}
	else
	{
		printf("通讯录中未找到 %s \n", name);
	}
	
}
//3.查找指定联系人(这里以查询联系人的姓名为例)
void SearchContact(Contact* pc)
{
	assert(pc);

	printf("请输入查找的联系人的姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	//查找联系人是否存在,存在则ret大于等于0
	int ret = ExistContact(pc, name);
	if (ret >= 0)
	{
		printf("%-8s%-12s%-17s%-8s%-8s%-8s\n", "序号", "姓名", "手机号", "年龄", "性别", "地址");
		printf("%-8d%-12s%-17s%-8d%-8s%-8s\n",
			ret+1, pc->data[ret].name, pc->data[ret].phone, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].address);
	}
	else
	printf("未找到 %s \n", name);
}
//4.修改指定联系人的信息
void ModifyContact(Contact* pc)
{
	assert(pc);

	printf("请输入需要修改的联系人:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	//标记所需修改的联系人的数组下标
	int ret = ExistContact(pc, name);

	//联系人存在则修改
	if (ret >= 0)
	{
		printf("请输入名字:");
		scanf("%s", pc->data[ret].name);
		printf("请输入年龄:");
		scanf("%d", &(pc->data[ret].age));
		printf("请输入性别:");
		scanf("%s", pc->data[ret].sex);
		printf("请输入电话:");
		scanf("%s", pc->data[ret].phone);
		printf("请输入地址:");
		scanf("%s", pc->data[ret].address);

		printf(" %s 添加成功\n", pc->data[ret].name);
	}
	else
	{
		printf("联系人输入有误\n");
	}
}
//5.将已添加联系人的信息进行排序(这里以联系人名字的首字母为例)
int cmp_stu_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	assert(pc);

	qsort(pc->data, pc->size, sizeof(pc->data[pc->size]),cmp_stu_name);
}
//6.展示通讯录的信息
void ShowContact(Contact* pc)
{
	assert(pc);

	printf("%-8s%-12s%-17s%-8s%-8s%-8s\n", "序号", "姓名","手机号","年龄","性别","地址");
	for (int i = 0; i < pc->size; i++)
	{
		printf("%-8d%-12s%-17s%-8d%-8s%-8s\n",
			i+1, pc->data[i].name, pc->data[i].phone, pc->data[i].age, pc->data[i].sex,pc->data[i].address);
	}
}
//7.销毁通讯录
void DestortContact(Contact* pc)
{
	assert(pc);

	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;
}
//8.退出通讯录
void ExitContact(Contact*pc)
{
	assert(pc);

	DestortContact(pc);
	printf("欢迎您下次使用\n");

	exit(-1);
}

 3.3 主函数 main.c

#include"contact.h"

//菜单选项
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
	
};
//菜单
void menu()
{
	printf("*****************************************\n");
	printf("**** 1. 添加联系人     2. 删除联系人 ****\n");
	printf("**** 3. 查找联系人     4. 修改联系人 ****\n");
	printf("**** 5. 展示通讯录     6. 联系人排序 ****\n");
	printf("**** 0. 退出程序                     ****\n");
	printf("*****************************************\n");
}

int main()
{
	//创建通讯录
	Contact contact;
	//初始化通讯录
	InitConctact(&contact);
	do
	{
		menu();

		int choice = 0;
		scanf("%d", &choice);
		
		switch (choice)
		{
		case ADD:
			AddContact(&contact);
			break;
		case DEL:
			DelContact(&contact);
			break;
		case SEARCH:
			SearchContact(&contact);
			break;
		case MODIFY:
			ModifyContact(&contact);
			break;
		case SHOW:
			ShowContact(&contact);
			break;
		case SORT:
			SortContact(&contact);
			break;
		case EXIT:
			ExitContact(&contact);
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
		system("pause");
		system("cls");

	} while (1);
	return 0;
}

4 .调试技巧及注意事项

  以下调试技巧和注意事项均为作者在写代码时发现的问题,在这里写下希望能帮到遇到相似问题的朋友,如果你遇到过一些困扰你的问题欢迎在评论区中提出,大家一起进步!

4.1 调试技巧

1.可以先把2.6中的展示通讯录信息写出,这样一来方便观察增删查改的信息是否有误。

2.也可以先不写菜单,写一个test()测试函数,写一个功能测试一个功能,这样可以避免出现错误而不知道从哪里开始调试更改。

4.2注意事项

1. 行参用指针表示,为了在传参时节省空间。如果传实参的时候Contact不是以地址的形式传输,注意加上&符号来传地址

2.开辟空间和增容是注意转换的指针类型,开辟的空间均是为联系人数组开辟的,不要错误地给通讯录数据类型开辟内存空间

5.结语

  如果这段代码对你来说可能很简单,那已经说明了你的c语言基本的代码书写能力已经很棒了。继续挑战更有难度的项目吧。

  如果感觉这段代码自己理解起来有点吃力,也不要灰心。整段代码在细节和逻辑性上确实有一定的难度,刚刚起步都会有点困难,多看几遍,多花点时间能自己独立的敲出这段代码就是成功!走出了这第一步后面的路也会变得轻松。

                                       感谢大家的阅读,这篇分享到这里就结束了!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值