链表实现一个通讯录

没修完的bug。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

2.实现一个通讯录;

通讯录可以用来存储1000个人的信息,每个人的信息包括:
姓名、性别、年龄、电话、住址


提供方法:
1. 添加联系人信息
2. 删除指定联系人信息
3. 查找指定联系人信息
4. 修改指定联系人信息
5. 显示所有联系人信息
6. 清空所有联系人

7. 以名字排序所有联系人

完整代码请滑到页尾

1. 添加联系人信息函数

思路:判断当前从主函数过来的结构体指针是否为空,为空就为它开辟一块空间,然后给这块空间添加联系人信息,如果不是空就找到链表的最后一个结点,在该结点后面开辟一块空间,然后给这块空间添加联系人信息,添加完毕后,最后的结点的结构体成员变量一定要指向空。

 
 
void add_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//临时联系人结构体指针
	struct contacts *tmp;
	//临时联系人结构体指针
	struct contacts *tmp_end;


	if (*pp == NULL)
	{
		*pp = (struct contacts *)malloc(sizeof(struct contacts));
		tmp = *pp;
	}
	else
	{
		tmp = (struct contacts *)malloc(sizeof(struct contacts));
		tmp_end = *pp;
		while (tmp_end->next )//找到最后一个结点
		{
			tmp_end = tmp_end->next;
		}
		tmp_end->next = tmp;//最后一个结点指向新开辟的结点
	}




	printf("输入姓名\n");
	getchar();//接收回车键
	gets(tmp_string);
	strcpy(tmp->name, tmp_string);


	printf("输入地址\n");
	gets(tmp_string);
	strcpy(tmp->address, tmp_string);


	printf("输入年龄\n");
	scanf("%d", &(tmp->age));


	printf("输入性别 1代表男 2代表女\n");
	scanf("%d",&(tmp->sex));


	printf("输入电话\n");
	getchar();//接收回车键
	gets(tmp_string);
	strcpy(tmp->phone, tmp_string);

	tmp->next = NULL;//最后一个结点的指针指向空,

	printf("添加成功\n");
	peopple_num++;
}



2. 删除指定联系人信息函数

思路:输入你所要删除联系人的姓名,然后遍历整个链表,如果找到匹配的先分类讨论,如果是第一个结点找到,并且后面没有结点了,直接释放第一个结点内存,并让*pp(等同于主函数中的con)指向空;如果是第一个结点找到,并且后面依然有结点,让*pp(等同于主函数中的con)指向它后面的结点,然后释放该结点;如果是在最后一个结点找到,释放该结点,前一个结点的后面指向空;其他在中间找到匹配的情况则上一个结点指向下一个结点,释放当前结点。

void delete_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//找到的匹配的人数
	int count = 0;
	//定义一个临时联系人结构体变量
	struct contacts *tmp = *pp;//指向第一个结点
	struct contacts *tmp_delete;//指向第二个结点
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		tmp_delete = tmp->next;
		getchar();//接收回车键
		printf("请输入所要删除联系人的姓名\n");
		gets(tmp_string);
		printf("删除结果\n");

		if (!strcmp(tmp->name, tmp_string))//如果在第一个结点找到了的话
		{
			if (tmp->next == NULL)//如果只有一个结点
			*pp=NULL;
			else
			*pp = tmp->next;//让链表本身指向第二个结点

			free(tmp);//释放第一个结点的内存
			tmp = NULL;
			tmp_delete = NULL;
			count++;
			printf("删除成功!\n");
			peopple_num--;
		}

		while (tmp_delete!=NULL)
		{
			if (!strcmp(tmp_delete->name, tmp_string))//如果找到了的话
			{
				if (tmp_delete->next == NULL)//如果在最后一个结点找到
				{
					tmp->next=NULL;
				}
				else
				{
					tmp->next = tmp_delete->next;
				}
				free(tmp_delete);
				count++;
				printf("删除成功!\n");
				peopple_num--;
				break;
			}
			tmp = tmp->next;
			tmp_delete = tmp_delete->next;
		}

		if (0 == count)
		{
			printf("通讯录里没有此人\n\r\n");
		}
	}
}


扫描二维码关注公众号,回复: 1529788 查看本文章

3. 查找指定联系人信息函数

思路:与删除结点的寻找方式差不多,遍历整个链表,然后打印出匹配的结点的数据。

void seek_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//找到的匹配的人数
	int count = 0;
	//定义一个临时联系人结构体变量
	struct contacts *tmp=*pp;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		getchar();//接收回车键
		printf("请输入所要查找联系人的姓名\n");
		gets(tmp_string);
		printf("查找结果\n");
		while (tmp)
		{
			if (!strcmp(tmp->name, tmp_string))//如果找到了的话
			{
				printf("姓名: %-10s 地址:%-10s 年龄:%-10d  性别:%-10s  电话:%-20s \n", tmp->name, tmp->address, tmp->age, Sex[tmp->sex], tmp->phone);//打印所有信息
				count++;//找到一人匹配
			}
			tmp = tmp->next;
		
		}
		if (0 == count)
		{
			printf("查无此人\n\r\n");
		}
	}
}

4. 修改指定联系人信息函数

思路:依然是先遍历整个链表,找到匹配的结点,进行修改结点的数据

void alter_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//定义一个临时联系人结构体变量
	struct contacts *tmp = *pp;
	//找到的匹配的人数
	int count = 0;
	//输入量
	int input=0;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		getchar();//接收回车键
		printf("请输入所要修改联系人的姓名\n");
		gets(tmp_string);
		while (tmp)
		{
			if (!strcmp(tmp->name, tmp_string))//如果找到了的话
			{
				do
				{
					printf("请选择修改联系人的属性\n");
					printf("0.退出\n");
					printf("1.姓名\n");
					printf("2.年龄\n");
					printf("3.性别\n");
					printf("4.电话\n");
					printf("5.地址\n");
					printf("请选择>");
					scanf("%d",&input);

					switch (input)
					{
					case 1:getchar(); printf("新名字\n"); scanf("%s", tmp->name); break;
					case 2:getchar(); printf("新年龄\n"); scanf("%d", &(tmp->age)); break;
					case 3:getchar(); printf("新性别 1男  2女\n"); scanf("%d", &(tmp->sex)); break;
					case 4:getchar(); printf("新电话\n"); scanf("%s", tmp->phone); break;
					case 5:getchar(); printf("新地址\n"); scanf("%s", tmp->address); break;
					}
				} while (input);

				printf("修改结果\n");
				printf("姓名: %-10s 地址:%-10s 年龄:%-10d  性别:%-10s  电话:%-20s \n", tmp->name, tmp->address, tmp->age, Sex[tmp->sex], tmp->phone);//打印所有信息
				count++;//找到一人匹配
				break;
			}
			tmp = tmp->next;
		}

		if (0 == count)
		{
			printf("没有搜索到此人\n\r\n");
		}
	}
}

5. 显示所有联系人信息

思路:遍历整个链表,把每一项都打印出来

void show_all(struct contacts **pp)
{
	//定义一个临时联系人结构体变量
	struct contacts *tmp;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		tmp = *pp;
		printf("显示所有联系人\n");
		while (tmp)
		{
			printf("姓名: %-10s 地址:%-10s 年龄:%-10d  性别:%-10s  电话:%-20s \n",tmp->name, tmp->address,tmp->age,Sex[tmp->sex],tmp->phone);
			tmp = tmp->next;
		}
	}
}

6. 清空所有联系人函数

思路:利用递归先找到最后一个结点释放掉,再回到上一级递归把倒数第二个结点释放掉,一次类推,最后释放掉第一个结点

并且最后一定要*pp=NULL;

void clear(struct contacts *p)
{
	if (p->next == NULL)//如果当前结点是最后一个结点
	{
		free(p);//释放本结点的内存
		p = NULL;
	}
	else //如果当前结点不是最后一个结点
	{
		clear(p->next);//递归到下一结点
		free(p);//释放本结点内存
		p= NULL;
	}

}

//6.	清空所有联系人
void clear_all(struct contacts **pp)
{
	//定义一个临时联系人结构体变量
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\n\r\n");
	}
	else
	{
		clear(*pp);//反向递归删除链表
		*pp = NULL;
		printf("\n\r\n已清空所有联系人!\n\n\r\n");
		peopple_num = 0;
	}
	
}

7. 以名字排序所有联系人函数

思路:排序中交换位置的方式不是用交换数据的方法,而是通过改变指向关系达到改变位置

如果总共只有一个结点不需要排序

如果前面只有两个结点 想要改变tmp1---->tmp2---->NULL的指向关系

图解 tmp1---->tmp2---->NULL的指向关系


第一步:tmp1->next=tmp2->next;


第二步:tmp2-next=tmp1;


完成位置交换

如果前面只三以上结点 想要改变tmp----> tmp1---->tmp2---->NULL的指向关系


	

第一步:tmp1->next = tmp2->next;


第二步:tmp2->next = tmp1;


第三步:tmp->next = tmp2;


即实现了tmp1与tmp2的位置互换

然后进行迭代,进行下一次循环,迭代过程要讨论tmp1与tmp2是否交换来决定迭代方式。

有了上面的基础,就可以通过冒泡法完成排序啦。

void sort_by_name(struct contacts **pp)
{
	int i = 0;
	int j = 0;
	//临时联系人结构体指针1
	struct contacts *tmp1= *pp;
	//临时联系人结构体指针2
	struct contacts *tmp2;
	//临时联系人结构体指针存放中转的地址
	struct contacts *tmp;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\n\r\n");
	}

	else
	{
		//如果当前是最后一个结点不需要排序
		if (tmp1->next == NULL)
		{
			;
		}
		else
		{
			for (i = peopple_num-1; i >0; i--)
			{
				//内层循环结束进行初始化
				tmp = *pp;
				tmp1 = *pp;
				tmp2= (*pp)->next;
				for (j=0;j<i;j++)
				{
					if (strcmp(tmp1->name, tmp2->name)>0)
					{
						if (j==0)//第一个结点和第二个结点比较时
						{
							tmp1->next = tmp2->next;
							tmp2->next = tmp1;
							*pp = tmp2;
							//整体后推一个结点 三句话顺序不能颠倒
							tmp = tmp2;
							tmp1 = tmp2->next;
							tmp2 = tmp1->next;
					
						}
						else if(j>0)
						{
							tmp1->next = tmp2->next;
							tmp2->next = tmp1;
							tmp->next = tmp2;
							//整体后推一个结点
							tmp = tmp->next;
							tmp1 = tmp2->next;
							tmp2 = tmp1->next;
						}
					}
					else//没有交换 正常后推一个结点
					{
						if (j == 0)//第一个结点和第二个结点比较时
						{
							tmp1 = tmp1->next;
							tmp2 = tmp2->next;
						}
						else if (j>0)
						{
							tmp = tmp->next;
							tmp1 = tmp1->next;
							tmp2 = tmp2->next;
						}
					}
				}
				
			}
		}
	}
}
完整代码
#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<stdlib.h>

#pragma warning (disable:4996)
//记录通讯录人数
int peopple_num = 0;
char *Sex[] = { 0 ,"男","女" };

//定义一个联系人结构体
struct contacts
{
	char name[20];//姓名
	char address[10];//地址
	int sex;//性别
	int age;//年龄
	char phone[20];//电话
	struct contacts* next;//指向下一个结点
};

//1.	添加联系人信息
void add_contacts(struct contacts **pp);

//2.	删除指定联系人信息
void delete_contacts(struct contacts **pp);

//3.	查找指定联系人信息
void seek_contacts(struct contacts **pp);

//4.	修改指定联系人信息
void alter_contacts(struct contacts **pp);

//5.	显示所有联系人信息
void show_all(struct contacts **pp);

//6.	清空所有联系人
void clear_all(struct contacts **pp);

//7.	以名字排序所有联系人
void sort_by_name(struct contacts **pp);

//8.打印菜单
void menu();



int main()
{
	int input=0;
	//定义一个指向联系人链表的指针
	struct contacts *con=NULL;
	//定义一个函数指针数组
	void(*p[8])(struct contacts **pp) = { 0,add_contacts ,delete_contacts ,seek_contacts ,alter_contacts ,show_all,clear_all,sort_by_name };
	do
	{
		menu();
		printf("\n请输入你的选择>");
		scanf("%d", &input);
		if (input <= 7 && input >= 1)
		{
			(*p[input])(&con);
		}
		else if (input != 0)
		{
			printf("输入有误!\n");
		}
	} while (input);

	printf("你已经退出程序\n");
	system("pause");
	return 0;
}

void menu()
{
	printf("\n           通讯录             \n");

	printf("    已添加人数:%-4d    请选择\n", peopple_num);

	printf("    0.退出                     \n");

	printf("    1.添加联系人信息           \n");

	printf("    2.删除指定联系人信息       \n");

	printf("    3.查找指定联系人信息       \n");

	printf("    4.修改指定联系人信息       \n");

	printf("    5.显示所有联系人信息       \n");

	printf("    6.清空所有联系人           \n");

	printf("    7.以名字排序所有联系人     \n");

}


//1.	添加联系人信息
void add_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//临时联系人结构体指针
	struct contacts *tmp;
	//临时联系人结构体指针
	struct contacts *tmp_end;

	if (*pp == NULL)
	{
		*pp = (struct contacts *)malloc(sizeof(struct contacts));
		tmp = *pp;
	}
	else
	{
		tmp = (struct contacts *)malloc(sizeof(struct contacts));
		tmp_end = *pp;
		while (tmp_end->next )//找到最后一个结点
		{
			tmp_end = tmp_end->next;
		}
		tmp_end->next = tmp;//最后一个结点指向新开辟的结点
	}


	printf("输入姓名\n");
	getchar();//接收回车键
	gets(tmp_string);
	strcpy(tmp->name, tmp_string);

	printf("输入地址\n");
	gets(tmp_string);
	strcpy(tmp->address, tmp_string);

	printf("输入年龄\n");
	scanf("%d", &(tmp->age));

	printf("输入性别 1代表男 2代表女\n");
	scanf("%d",&(tmp->sex));

	printf("输入电话\n");
	getchar();//接收回车键
	gets(tmp_string);
	strcpy(tmp->phone, tmp_string);



	tmp->next = NULL;

	printf("添加成功\n");
	peopple_num++;
}

//2.	删除指定联系人信息
void delete_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//找到的匹配的人数
	int count = 0;
	//定义一个临时联系人结构体变量
	struct contacts *tmp = *pp;//指向第一个结点
	struct contacts *tmp_delete;//指向第二个结点
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		tmp_delete = tmp->next;
		getchar();//接收回车键
		printf("请输入所要删除联系人的姓名\n");
		gets(tmp_string);
		printf("删除结果\n");

		if (!strcmp(tmp->name, tmp_string))//如果在第一个结点找到了的话
		{
			if (tmp->next == NULL)//如果只有一个结点
			*pp=NULL;
			else
			*pp = tmp->next;//让链表本身指向第二个结点

			free(tmp);//释放第一个结点的内存
			tmp = NULL;
			tmp_delete = NULL;
			count++;
			printf("删除成功!\n");
			peopple_num--;
		}

		while (tmp_delete!=NULL)
		{
			if (!strcmp(tmp_delete->name, tmp_string))//如果找到了的话
			{
				if (tmp_delete->next == NULL)//如果在最后一个结点找到
				{
					tmp->next=NULL;
				}
				else
				{
					tmp->next = tmp_delete->next;
				}
				free(tmp_delete);
				count++;
				printf("删除成功!\n");
				peopple_num--;
				break;
			}
			tmp = tmp->next;
			tmp_delete = tmp_delete->next;
		}

		if (0 == count)
		{
			printf("通讯录里没有此人\n\r\n");
		}
	}
}

//3.	查找指定联系人信息
void seek_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//找到的匹配的人数
	int count = 0;
	//定义一个临时联系人结构体变量
	struct contacts *tmp=*pp;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		getchar();//接收回车键
		printf("请输入所要查找联系人的姓名\n");
		gets(tmp_string);
		printf("查找结果\n");
		while (tmp)
		{
			if (!strcmp(tmp->name, tmp_string))//如果找到了的话
			{
				printf("姓名: %-10s 地址:%-10s 年龄:%-10d  性别:%-10s  电话:%-20s \n", tmp->name, tmp->address, tmp->age, Sex[tmp->sex], tmp->phone);//打印所有信息
				count++;//找到一人匹配
			}
			tmp = tmp->next;
		
		}
		if (0 == count)
		{
			printf("查无此人\n\r\n");
		}
	}
}

//4.	修改指定联系人信息
void alter_contacts(struct contacts **pp)
{
	//临时字符串
	char tmp_string[20];
	//定义一个临时联系人结构体变量
	struct contacts *tmp = *pp;
	//找到的匹配的人数
	int count = 0;
	//输入量
	int input=0;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		getchar();//接收回车键
		printf("请输入所要修改联系人的姓名\n");
		gets(tmp_string);
		while (tmp)
		{
			if (!strcmp(tmp->name, tmp_string))//如果找到了的话
			{
				do
				{
					printf("请选择修改联系人的属性\n");
					printf("0.退出\n");
					printf("1.姓名\n");
					printf("2.年龄\n");
					printf("3.性别\n");
					printf("4.电话\n");
					printf("5.地址\n");
					printf("请选择>");
					scanf("%d",&input);

					switch (input)
					{
					case 1:getchar(); printf("新名字\n"); scanf("%s", tmp->name); break;
					case 2:getchar(); printf("新年龄\n"); scanf("%d", &(tmp->age)); break;
					case 3:getchar(); printf("新性别 1男  2女\n"); scanf("%d", &(tmp->sex)); break;
					case 4:getchar(); printf("新电话\n"); scanf("%s", tmp->phone); break;
					case 5:getchar(); printf("新地址\n"); scanf("%s", tmp->address); break;
					}
				} while (input);

				printf("修改结果\n");
				printf("姓名: %-10s 地址:%-10s 年龄:%-10d  性别:%-10s  电话:%-20s \n", tmp->name, tmp->address, tmp->age, Sex[tmp->sex], tmp->phone);//打印所有信息
				count++;//找到一人匹配
				break;
			}
			tmp = tmp->next;
		}

		if (0 == count)
		{
			printf("没有搜索到此人\n\r\n");
		}
	}
}

//5.	显示所有联系人信息
void show_all(struct contacts **pp)
{
	//定义一个临时联系人结构体变量
	struct contacts *tmp;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\r\n");
	}
	else
	{
		tmp = *pp;
		printf("显示所有联系人\n");
		while (tmp)
		{
			printf("姓名: %-10s 地址:%-10s 年龄:%-10d  性别:%-10s  电话:%-20s \n",tmp->name, tmp->address,tmp->age,Sex[tmp->sex],tmp->phone);
			tmp = tmp->next;
		}
	}
}


void clear(struct contacts *p)
{
	if (p->next == NULL)//如果当前结点是最后一个结点
	{
		free(p);//释放本结点的内存
		p = NULL;
	}
	else //如果当前结点不是最后一个结点
	{
		clear(p->next);//递归到下一结点
		free(p);//释放本结点内存
		p= NULL;
	}

}

//6.	清空所有联系人
void clear_all(struct contacts **pp)
{
	//定义一个临时联系人结构体变量
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\n\r\n");
	}
	else
	{
		clear(*pp);//反向递归删除链表
		*pp = NULL;
		printf("\n\r\n已清空所有联系人!\n\n\r\n");
		peopple_num = 0;
	}
	
}




//7.	以名字排序所有联系人
void sort_by_name(struct contacts **pp)
{
	int i = 0;
	int j = 0;
	//临时联系人结构体指针1
	struct contacts *tmp1= *pp;
	//临时联系人结构体指针2
	struct contacts *tmp2;
	//临时联系人结构体指针存放中转的地址
	struct contacts *tmp;
	if (*pp == NULL)
	{
		printf("\n\r\n通讯录暂时没有联系人\n\n\r\n");
	}

	else
	{
		//如果当前是最后一个结点不需要排序
		if (tmp1->next == NULL)
		{
			;
		}
		else
		{
			for (i = peopple_num-1; i >0; i--)
			{
				//内层循环结束进行初始化
				tmp = *pp;
				tmp1 = *pp;
				tmp2= (*pp)->next;
				for (j=0;j<i;j++)
				{
					if (strcmp(tmp1->name, tmp2->name)>0)
					{
						if (j==0)//第一个结点和第二个结点比较时
						{
							tmp1->next = tmp2->next;
							tmp2->next = tmp1;
							*pp = tmp2;
							//整体后推一个结点 三句话顺序不能颠倒
							tmp = tmp2;
							tmp1 = tmp2->next;
							tmp2 = tmp1->next;
					
						}
						else if(j>0)
						{
							tmp1->next = tmp2->next;
							tmp2->next = tmp1;
							tmp->next = tmp2;
							//整体后推一个结点
							tmp = tmp->next;
							tmp1 = tmp2->next;
							tmp2 = tmp1->next;
						}
					}
					else//没有交换 正常后推一个结点
					{
						if (j == 0)//第一个结点和第二个结点比较时
						{
							tmp1 = tmp1->next;
							tmp2 = tmp2->next;
						}
						else if (j>0)
						{
							tmp = tmp->next;
							tmp1 = tmp1->next;
							tmp2 = tmp2->next;
						}
					}
				}
				
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq1910084514/article/details/80458570
今日推荐