单链表写通讯录
单链表实现通讯录,增加,删除,更改一个联系人等功能。其中增加了一个内存池功能,用于对废弃内存的回收和利用。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 1024
void addPerson(struct Presonlist **node);//添加一个联系人
void displayContact(struct Presonlist *node);//显示通信录
void changPerson(struct Presonlist *node, char **str1, char **str2);//更改联系人
void delPerson(struct Presonlist **node, char *str);//删除一个联系人
void welcome(void);//欢迎界面
struct Presonlist *pool = NULL;//定义一个内存池
void pooldelete(void);
int count;
struct Presonlist {//定义一个结构体
char name[200];
char number[100];
struct Presonlist *next;
};
void addPerson(struct Presonlist **node)
{
struct Presonlist *newlist;
static struct Presonlist *tail= *node;//定义尾指针
if (pool != NULL)//如果内存池非空,则直接从里面获取空间
{
newlist = pool;
pool = pool->next;
count--;
}
//如果内存池为空,则用malloc申请空间
else {
newlist = (struct Presonlist *)malloc(sizeof(struct Presonlist));
if (newlist == NULL)
{
printf("分配失败\n");
exit(1);
}
}
printf("请输入新增联系人姓名\n");
scanf_s("%s", newlist->name,sizeof(newlist->name));
printf("请输入新增联系人电话号码\n");
scanf_s("%s", newlist->number, sizeof(newlist->number));
if(*node == NULL)//如果指针为空,直接将新节点插入即可
{
*node = newlist;
newlist->next = NULL;
}
else//采用尾插法
{
tail->next = newlist;
newlist->next = NULL;
}
tail = newlist;//保证尾指针指向链表的最末尾
}
void displayContact(struct Presonlist *node)
{
while (node != NULL)
{
printf("%s:%s\n", node->name,node->number);
node = node->next;
}
}
void delPerson(struct Presonlist **node, char *str)//输入链表和要删除的字符串
{
struct Presonlist *current, *previous, *newlist;
current = *node;
previous = NULL;
while (current != NULL && strcmp(current->name, str)&& strcmp(current->number, str))//如果当前指针不为空而且不是我们查找的名字或者号码,程序就继续执行。
{
previous = current;//指针后移一个
current = current->next;
}
if (current == NULL)
{
printf("没有找到或者链表为空\n");
}
else
{
if (previous == NULL)//如果只有一个结点current,previous处于初始化状态
{
*node = current->next;
}
else {
previous->next = current->next;//删除节点
}
if (count < MAX)//如果内存池大小小于MAX,则把删除的current存放在pool中
{
if (pool != NULL)//如果pool不为空。采用头插法插入current
{
current->next = pool;
pool = current;
}
else//否则直接插入即可
{
pool = current;
current->next = NULL;
}
count++;
}
else//如果内存池大小大于MAX,直接释放current结点
{
free(current);
}
}
}
void Contactexit(struct Presonlist **node)//直接释放所有的链表结点
{
struct Presonlist *nextlist;
while (*node!=NULL)
{
nextlist = (*node)->next;
free(*node);
*node = nextlist;
}
}
void pooldelete(void)//删除内存池
{
struct Presonlist *nextlist;
while (pool != NULL)
{
nextlist = pool->next;
free(pool);
pool = nextlist;
}
}
struct Presonlist *findPerson(struct Presonlist *node,char *str)
{
struct Presonlist *sear=node;
while ((sear!=NULL)&&(strcmp(sear->name,str))&&(strcmp(sear->number, str)))//如果不为空而且没有找到则继续循环
{
sear = sear->next;
}
if (sear != NULL)//如果不为空
{
if (!strcmp(sear->name, str) || !strcmp(sear->number, str))//找到名字或者电话号码则返回
{
return sear;
}
else {
printf("查找错误\n");
}
}
else
{
printf("没有找到\n");
return sear;
}
}
void changPerson(struct Presonlist *node, char *str1, char *str2)
{
struct Presonlist *sear = node;
while ((sear != NULL) && (strcmp(sear->name, str1))&& (strcmp(sear->number, str1)))//如果链表不为空,而且没有找到
{
sear = sear->next;
}
if (sear != NULL)
{
if (!strcmp(sear->name, str1))//如果找到的str1是更改联系人的名字
{
memset(sear->name, 0, sizeof(sear->name));//先把名字置为0
strcpy_s(sear->name, strlen(str2) + 1, str2);//再把str2拷贝到名字中
}
else if (!strcmp(sear->number, str1))//不然就是电话号码
{
memset(sear->number, 0, sizeof(sear->number));
strcpy_s(sear->number, strlen(str2) + 1, str2);
}
else {
printf("更改失败,请重新输入\n");
}
}
else
{
printf("没有找到,请重新输入\n");
}
}
void welcome(void)
{
printf("欢迎使用袁强的通信录\n\
请输入以下命令:\n\
--- 1:新建联系人 ---|\n\
--- 2:查找联系人 ---|\n\
--- 3:删除联系人 ---|\n\
--- 4:显示通讯录 ---|\n\
--- 5:更改联系人 ---|\n\
--- 6:删除通讯录 ---|\n\
--- 7:退出通讯录 ---|\n");
}
int main(void)
{
struct Presonlist *node = NULL;
struct Presonlist *findlist = NULL;
char c = 0;
char input[100] = {0};
char change[100] = { 0 };
welcome();
while (1)
{
c = getchar();
switch (c)
{
case '1':addPerson(&node);
printf("count:%d\n", count);
printf("增加联系人成功\n");
break;
case '2':
printf("请输入要查找的联系人或者号码\n");
scanf_s("%s", input, sizeof(input));
findlist = findPerson(node, input);
if (findlist != NULL)
{
printf("查找出的联系人是%s:%s\n", findlist->name, findlist->number);
}
break;
case '3':
printf("请输入要删除的联系人/号码\n");
scanf_s("%s", change, sizeof(change));
delPerson(&node, change);
printf("count:%d\n",count);
break;
case '4':
displayContact(node);
break;
case '5':
printf("请输入需要更改的名字/电话号码\n");
memset(input, 0, sizeof(input));
scanf_s("%s", input, sizeof(input));
printf("请输入更改后的名字/电话号码\n");
scanf_s("%s", change, sizeof(change));
changPerson(node, input, change);
printf("更改后的联系人列表:\n");
displayContact(node);
break;
case '6':
Contactexit(&node);
pooldelete();
printf("已删除所有列表\n");
welcome();
break;
case '7':
return 0;
}
}