没修完的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");
}
}
}
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;
}
}
}
}
}
}
}