C语言 单链表通讯录基础版实现,保证看完都直呼easy

C语言 单链表实现通讯录基础版,保证看完都大呼简单!

—————————————————————————————————
首先在写通讯录之前,必须明确我们的需求
因为是基础版,我在这里暂时只实现以下一些需求(绝不是因为我暂时只写了这么些):

/*
添加联系人信息
删除指定联系人信息
查找指定联系人信息
修改指定联系人信息
显示所有联系人信息
清空所有联系人
*/

—————————————————————————————————
首先是创建我们的联系人结构体

typedef struct Contacts 
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char address[ADDRESS_MAX];
	char numbers[NUMBERS_MAX];
	struct Contacts* next;
}Contacts;

—————————————————————————————————
添加联系人
这里最大的要点,也是经常有人会犯错误的点,就是传入结构体头指针时,必须得是二级指针,因为我们是要对指针进行修改的。
而且我们需要对链表一开始是否为NULL进行分类讨论

void ConInfor(Contacts* con)
{
	printf("请输入姓名:");
	scanf("%s", con->name);
	printf("请输入年龄:");
	scanf("%d", &con->age);
	printf("请输入性别:");
	scanf("%s", con->sex);
	printf("请输入家庭地址:");
	scanf("%s", con->address);
	printf("请输入电话号码:");
	scanf("%s", con->numbers);
	con->next = NULL;
}

void AddContacts(Contacts** pphead)//一定是二级指针!!!!!
{
	Contacts* new_contacts = (Contacts*)malloc(sizeof(Contacts));
	ConInfor(new_contacts);
	if (*pphead == NULL)
	{
		*pphead = new_contacts;
	}
	else
	{
		Contacts* cur = *pphead;
		while (cur->next != NULL)
		{
			cur = cur->next;
		}
		cur->next = new_contacts;
	}
}

这里有个小细节,就是我把输入联系人单独封装成了一个函数,因为这块代码一定会在我们修改联系人那一个功能上用到。
—————————————————————————————————
删除联系人
我认为这一块是实现单链表通讯录的一个难点之一。
难点其一,还是二级指针
其二,就是如何在删除结点的同时,再连接被删除位置前后的结点。
其三,就是针对链表为NULL,只有一个结点和不止一个结点的三种情况的不同解决方法。

解决方法:1,链表为空,直接返回
2.仅有一个结点,删除(释放)结点,头结点置成NULL
3.多个结点,使用双指针,分别记录当前结点地址,和当前结点上一个的地址。

void DelContacts(Contacts** pphead)
{
	printf("请输入被删除联系人姓名:");
	char name[NAME_MAX];
	scanf("%s", name);
	int flag = 1;
	if (*pphead == NULL)//链表为空
	{
		printf("删除失败,通讯录为空!\n");
		return;
	}
	else if ((*pphead)->next==NULL)//链表有一个结点
	{
		if (strcmp(name, (*pphead)->name) == 0)
		{
			*pphead = NULL;
			printf("删除成功!\n");
			flag = 0;
		}
	}
	else//链表有多个结点
	{
		Contacts* prve =*pphead;
		Contacts* cur = *pphead;
		if (strcmp(name, cur->name) == 0)
		{
			*pphead = cur->next;
			printf("删除成功!\n");
			return;
		}
		while (cur != NULL)
		{
			if (strcmp(name,cur->name) == 0)
			{
				prve->next = cur->next;
				free(cur);
				flag = 0;
				printf("删除成功!\n");
				break;
			}
			prve = cur;
			cur = cur->next;
		}
	}
	if (flag == 1)
	{
		printf("查无此人,无法删除!\n");
	}
}

—————————————————————————————————
查找联系人
这一块就很简单了,和删除联系人的函数有很大的重叠部分,因为我们删除的时候就需要找到被删的联系人对不对?这里对一二级指针要求就不严格了,但我建议是用一级指针,防止误操作

void CheckContacts(Contacts* phead)
{
	Contacts* cur = phead;
	printf("请输入所要查找联系人姓名:");
	char name[NAME_MAX];
	scanf("%s", name);
	while (cur != NULL)
	{
		if (strcmp(name, cur->name) == 0)
		{
			printf("已找到!\n");
			printf("姓名                  年龄   性别   电话号码              住址\n");
			Print(cur);
			return;
		}
		cur = cur->next;
	}
	printf("查无此人!\n");
}

显示所有联系人信息
按照查找的方式,遍历链表时打印就欧克了。

void PrintContacts(Contacts* phead)
{
	if (phead == NULL)
	{
		printf("通讯录为空\n");
	}
	else
	{
		printf("姓名                  年龄   性别   电话号码              住址\n");
		while (phead != NULL)
		{
			Print(phead);
			phead = phead->next;
		}
	}
}

void Print(Contacts* phead)
{
	printf("%-20s  ", phead->name);//这里的-是左对齐,20是域宽
	printf("%-5d  ", phead->age);//这里的-是左对齐,5是域宽
	printf("%-5s  ", phead->sex);//这里的-是左对齐,5是域宽
	printf("%-20s  ", phead->numbers);
	printf("%-20s  \n", phead->address);
}

—————————————————————————————————
清空联系人
这一块就得注意了,可不能以为给头指针置NULL就拍拍屁股走人了,这就是典型的穿上裤子就不认人了,我们可不能做这样的程序猿。必须得挨个给每个结点释放了,防止内存泄漏。这里依然要用到双指针!!

void ClearContacts(Contacts** pphead)
{
	Contacts* prve = *pphead;
	Contacts* cur = *pphead;
	while (cur != NULL)
	{
		prve = cur;
		cur = cur->next;
		free(prve);
	}
	*pphead = NULL;//最后置NULL,才是负责的程序猿
	printf("已清空!\n");
}

源代码

.h文件

#define _CRT_SECURE_NO_WARNINGS
//宏定义
#define NAME_MAX 20
#define SEX_MAX 10
#define ADDRESS_MAX 20
#define NUMBERS_MAX 15
//头文件包含
#include
#include
#include

//枚举常量定义
enum Choose
{
	EXIT,
	ADD,
	DEL,
	CHECK,
	MODIFY,
	PRINT,
	CLEAR,
	SORT
};

//结构体定义
typedef struct Contacts 
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char address[ADDRESS_MAX];
	char numbers[NUMBERS_MAX];
	struct Contacts* next;
}Contacts;
//函数声明
void menu();
/*
添加联系人信息
删除指定联系人信息
查找指定联系人信息
修改指定联系人信息
显示所有联系人信息
清空所有联系人
*/

//同名同姓暂不处理

void AddContacts(Contacts** pphead);//添加联系人

void PrintContacts(Contacts* phead);//打印联系人

void Print(Contacts* phead);//打印单独封装

void DelContacts(Contacts** pphead);//删除联系人

void CheckContacts(Contacts* phead);//查找联系人,仅姓名

void ClearContacts(Contacts** pphead);//清空通讯录

void SortContacts(Contacts** pphead);


.c文件

#include"Contaction.h"

void menu()
{
	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");
}

void ConInfor(Contacts* con)
{
	printf("请输入姓名:");
	scanf("%s", con->name);
	printf("请输入年龄:");
	scanf("%d", &con->age);
	printf("请输入性别:");
	scanf("%s", con->sex);
	printf("请输入家庭地址:");
	scanf("%s", con->address);
	printf("请输入电话号码:");
	scanf("%s", con->numbers);
	con->next = NULL;
}

void AddContacts(Contacts** pphead)
{
	Contacts* new_contacts = (Contacts*)malloc(sizeof(Contacts));
	ConInfor(new_contacts);
	if (*pphead == NULL)
	{
		*pphead = new_contacts;
	}
	else
	{
		Contacts* cur = *pphead;
		while (cur->next != NULL)
		{
			cur = cur->next;
		}
		cur->next = new_contacts;
	}
}

void DelContacts(Contacts** pphead)
{
	printf("请输入被删除联系人姓名:");
	char name[NAME_MAX];
	scanf("%s", name);
	int flag = 1;
	if (*pphead == NULL)
	{
		printf("删除失败,通讯录为空!\n");
		return;
	}
	else if ((*pphead)->next==NULL)
	{
		if (strcmp(name, (*pphead)->name) == 0)
		{
			*pphead = NULL;
			printf("删除成功!\n");
			flag = 0;
		}
	}
	else
	{
		Contacts* prve =*pphead;
		Contacts* cur = *pphead;
		if (strcmp(name, cur->name) == 0)
		{
			*pphead = cur->next;
			printf("删除成功!\n");
			return;
		}
		while (cur != NULL)
		{
			if (strcmp(name,cur->name) == 0)
			{
				prve->next = cur->next;
				free(cur);
				flag = 0;
				printf("删除成功!\n");
				break;
			}
			prve = cur;
			cur = cur->next;
		}
	}
	if (flag == 1)
	{
		printf("查无此人,无法删除!\n");
	}
}

void CheckContacts(Contacts* phead)
{
	Contacts* cur = phead;
	printf("请输入所要查找联系人姓名:");
	char name[NAME_MAX];
	scanf("%s", name);
	while (cur != NULL)
	{
		if (strcmp(name, cur->name) == 0)
		{
			printf("已找到!\n");
			printf("姓名                  年龄   性别   电话号码              住址\n");
			Print(cur);
			return;
		}
		cur = cur->next;
	}
	printf("查无此人!\n");
}

void PrintContacts(Contacts* phead)
{
	if (phead == NULL)
	{
		printf("通讯录为空\n");
	}
	else
	{
		printf("姓名                  年龄   性别   电话号码              住址\n");
		while (phead != NULL)
		{
			Print(phead);
			phead = phead->next;
		}
	}
}

void Print(Contacts* phead)
{
	printf("%-20s  ", phead->name);
	printf("%-5d  ", phead->age);
	printf("%-5s  ", phead->sex);
	printf("%-20s  ", phead->numbers);
	printf("%-20s  \n", phead->address);
}

void ClearContacts(Contacts** pphead)
{
	Contacts* prve = *pphead;
	Contacts* cur = *pphead;
	while (cur != NULL)
	{
		prve = cur;
		cur = cur->next;
		free(prve);
	}
	*pphead = NULL;
	printf("已清空!\n");
}

void SortContacts(Contacts** pphead)
{

}

int main()
{
	menu();
	int input = 0;
	Contacts *con=NULL;
	do {
        printf("请选择:\n");
        scanf("%d", &input);
		switch (input)
		{
		case EXIT:
			printf("已退出!\n");
			break;
		case ADD:
			AddContacts(&con);
			break;
		case DEL:
			DelContacts(&con);
			break;
		case CHECK:
			CheckContacts(con);
			break;
		case MODIFY:
			break;
		case PRINT:
			PrintContacts(con);
			break;
		case CLEAR:
			ClearContacts(&con);
			break;
		case SORT:
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}

以上呢,就是基础的通讯录实现啦,还有很多功能还未完善,比如排序同名同姓处理方法等,大家不妨可以关注我,我会马不停蹄的更新的进阶版的!!!
—————————————————————————————————

你可能感兴趣的:(c语言,c语言,链表,数据结构)