C语言使用双向循环链表实现通讯录

使用双向链表实现通讯录,实现添加功能、删除功能、查询功能、修改功能、显示功能。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct linkman
{
	char name[10];
	char Tel[20];
	struct linkman *prev;
	struct linkman *next;
}linkman;

int Menu(void);//主菜单
int menu2(void);
void InitList(struct linkman **head);//初始化链表

void Readfile(linkman *head);//从文件中读数据
void Writefile(linkman *head);//往文件中写数据

void Add(struct linkman *head);
void Add_one(struct linkman *head,char *name,char *Tel);
void Delete(struct linkman *head);
linkman *Search(struct linkman *head,char message[]);
linkman *Search_name(struct linkman *head,char message[]);
linkman *Search_tel(struct linkman *head,char message[]);
void GoSearch(struct linkman *head,struct linkman *p);
void Change(struct linkman *head);
void Print(struct linkman *head);//输出整个通讯录
void print(struct linkman *p);//输出查询出的单个联系人的信息
void Shifang(struct linkman *head);//释放所有节点

void main()
{
	struct linkman *address_list=NULL,*p=NULL;
	InitList(&address_list);
	Readfile(address_list);
	int num;
	char message[20];
	while(1)
	{
		num=Menu();
    	switch(num)
		{
        	case 1:Add(address_list);
				printf("\n");
				break;
			case 2:Delete(address_list);
				printf("\n");
				break;
			case 3:getchar();//把上一个输入的换行读入缓冲区,避免message读入
				printf("请输入要查找的联系人姓名或电话:");
				scanf("%s",message);
				p=Search(address_list,message);
				if(p)
				{
					print(p);
					GoSearch(address_list,p);
				}
				else
					printf("此联系人不存在!\n");
				printf("\n");
				break;
			case 4:Change(address_list);
				printf("\n");
				break;
			case 5:Print(address_list);
				printf("\n");
				break;
			case 0:Writefile(address_list);
				printf("已退出通讯录!\n");
				Shifang(address_list);
			    exit(0);
		    	printf("\n");
			default:printf("error!\n");
		}
	}
}

void Readfile(linkman *head)
{
	linkman *p=NULL;
	char name[10],Tel[20];
	FILE *fp=fopen("address_book.txt","r");
	fscanf(fp,"%s%s",name,Tel);
	while(!feof(fp))
	{
		printf("%s %s\n",name,Tel);
		Add_one(head,name,Tel);
		fscanf(fp,"%s%s",name,Tel);
	}
	fclose(fp);
}
void Writefile(linkman *head)
{
	linkman *p=head->next;
	FILE *fp=fopen("address_book.txt","w");
	for(;p!=head;p=p->next)
	{
		fwrite(p->name,strlen(p->name),1,fp);
		fputs(" ",fp);
		fwrite(p->Tel,strlen(p->Tel),1,fp);
		fputs("\n",fp);
	}
	fclose(fp);
}

int Menu(void)
{
	int choice;
	printf("                通讯录\n");
	printf("**************************************\n");
	printf("1.添加联系人\n");
	printf("2.删除联系人\n");
	printf("3.查找联系人\n");
    printf("4.编辑联系人\n");
	printf("5.显示所有联系人\n");
	printf("0.退出\n");
	printf("**************************************\n");
	printf("Please enter your choice:");
	scanf("%d",&choice);
	return choice;
}

int menu2(void)
{
	int num;
	printf("1.查看上一个联系人\n");
	printf("2.查看下一个联系人\n");
	printf("0.退出查询\n");
	printf("请输入你的选择:");
	scanf("%d",&num);
	return num;
}

void InitList(struct linkman **head)
{
	while((*head)==NULL)
	{
		*head=(struct linkman *)malloc(sizeof(struct linkman));
	}
	(*head)->next=(*head);
	(*head)->prev=(*head);
}

void Add(struct linkman *head)
{
	char name[10];
	char Tel[20];
	char choice;
	linkman *p=NULL,*q=NULL;
	printf("请输入联系人的姓名:");
	scanf("%s",name);
	printf("请输入联系人的电话:");
	scanf("%s",Tel);
	q=Search(head,name);
	if(q)
	{
		getchar();//把上一个输入的换行读入缓冲区,避免name读入
		while(1)
		{
			printf("此联系人已存在,是否替换(Y/N):");
			scanf("%c",&choice);
			if(choice=='Y'||choice=='y')
			{	
				strcpy(q->name,name);
				strcpy(q->Tel,Tel);
				printf("添加成功!\n");
				break;
			}
			else if(choice=='N'||choice=='n')
			{
				printf("取消添加!\n");
				break;
			}
			else
				continue;//若输入非'Y'、'N'的字符就继续询问
		}
	}
	else
	{
		Add_one(head,name,Tel);
		printf("添加成功!\n");
	}
}
void Add_one(struct linkman *head,char *name,char *Tel)
{
	linkman *p=NULL;
	while(!p)
		{
			p=(struct linkman *)malloc(sizeof(struct linkman));
		}
		strcpy(p->name,name);
		strcpy(p->Tel,Tel);
		//使用前插法插入新节点
		head->prev->next=p;
		p->prev=head->prev;
		p->next=head;
		head->prev=p;
}

void Delete(struct linkman *head)
{
	linkman *p=head;
	char name[10];
	char choice;
	printf("请输入要删除的联系人姓名:");
	scanf("%s",name);
	p=Search_name(head,name);
	if(p)
	{
		print(p);
		getchar();//把上一个输入的换行读入缓冲区,避免choice读入
		while(1)
		{
			printf("是否删除此联系人(Y/N):");
			scanf("%c",&choice);
			if(choice=='Y'||choice=='y')
			{	
				p->prev->next=p->next;
				p->next->prev=p->prev;
				free(p);
				printf("删除成功!\n");
				break;
			}
			else if(choice=='N'||choice=='n')
			{
				printf("取消删除!\n");
				break;
			}
			else
				continue;//若输入非'Y'、'N'的字符就继续询问
		}
		
	}
	else
		printf("此联系人不存在!\n");
}

linkman *Search(struct linkman *head,char message[])
{
	linkman *p=head;
	p=Search_name(head,message);
	if(p)
		return p;
	p=Search_tel(head,message);
	if(p)
		return p;
	return NULL;
}

linkman *Search_name(struct linkman *head,char message[])
{
	linkman *p=head;
	if(p->next!=head)
	{
		while(p->next!=head)
		{
			p=p->next;
			if(strcmp(p->name,message)==0)
				return p;
		}
	}
	return NULL;
}
linkman *Search_tel(struct linkman *head,char message[])
{
	linkman *p=head;
	if(p->next!=head)
	{
		while(p->next!=head)
		{
			p=p->next;
			if(strcmp(p->Tel,message)==0)
				return p;
		}
	}
	return NULL;
}


void GoSearch(struct linkman *head,struct linkman *p)
{
	int num;
	while(1)
	{
		num=menu2();
		switch(num)
		{
			case 1:p=p->next;
				if(p==head)
					p=p->next;
				print(p);
				break;
			case 2:p=p->prev;
				if(p==head)
					p=p->next;
				print(p);
				break;
			case 0:printf("已退出查询!\n");
				return;
			default:printf("error!\n");
				break;
		}
	}
}

void Change(struct linkman *head)
{
	linkman *p=NULL,*q=NULL;
	char name[10],choice;
	printf("请输入要编辑的联系人姓名:");
	scanf("%s",name);
	p=Search_name(head,name);
	int num;
	if(p)
	{
		print(p);
		printf("1.编辑姓名\n");
		printf("2.编辑电话\n");
		printf("0.取消编辑\n");
		printf("请输入你的选择:");
		scanf("%d",&num);
		switch(num)
		{
			case 1:printf("请输入修改后的姓名:");
				scanf("%s",name);
				while(1)
				{
					q=Search(head,name);
					if(q)
					{
						printf("此联系人已存在,是否继续修改(Y/N):");
						getchar();
						scanf("%c",&choice);
						if(choice=='Y'||choice=='y')
						{
							printf("请输入修改后的姓名:");
							scanf("%s",name);
						}
						else if(choice=='N'||choice=='n')
						{
							printf("已取消修改!\n");
							break;
						}
						else
							continue;
					}
					else
					{
						strcpy(p->name,name);
						printf("修改成功!\n");
						break;
					}
				}
				break;
			case 2:printf("请输入修改后的电话:");
				scanf("%s",p->Tel);
				printf("修改成功!\n");
				break;
			case 0:printf("已取消修改!\n");
				break;
			default:printf("error!\n");
		}
	}
	else
		printf("此联系人不存在!\n");
}

void Print(struct linkman *head)
{
	linkman *p=head;
	if(p->next==head)
		printf("通讯录为空!\n");
	else
	{
		printf("*-----------------------------------*\n");
		printf("      姓名   电话\n\n");
		while(p->next!=head)
		{
			p=p->next;
			printf("%10s   %s\n",p->name,p->Tel);
		}
		printf("*-----------------------------------*\n");
	}
}
void print(struct linkman *p)
{
	printf("*-----------------------------------*\n");
	printf("      姓名   电话\n\n");
	printf("%10s    %s\n",p->name,p->Tel);
	printf("*-----------------------------------*\n");
}

void Shifang(struct linkman *head)
{
	linkman *p=head;
	if(p->next!=head)
	{
		p=p->next;//释放掉头结点后面的那个节点
		p->prev->next=p->next;
		p->next->prev=p->prev;
		free(p);
		p=head;
	}
	free(p);//释放掉头结点
}

在相同目录下建立一个名为“address_book.txt”的txt文件,里面可以先写几个联系人的信息,中间用空格隔开。例如
在这里插入图片描述

发布了28 篇原创文章 · 获赞 4 · 访问量 2493

猜你喜欢

转载自blog.csdn.net/weixin_45050042/article/details/102512096
今日推荐