通讯录项目整理(链表法)

本文介绍了我通讯录项目各个功能的编写过程以及大体思路。

1.头文件以及结构体的定义

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
typedef char Elemtype;
typedef char Status;
typedef struct Node
{
	Elemtype name[10];
	Elemtype tel[12];
	struct Node *next;
}Node,*Address_list;

2.初始化过程

    申请头结点,使用malloc函数为头结点分配空间,让头指针指向头结点,头结点的指针域指向NULL。

    为什么要申请头结点?

    为了保证处理第一个节点(非头结点)和后面节点时候设计的算法相同,实现程序的高效性。

/************初始化****************/
Status Initaddress(Address_list *aptr)
{
	Node *p=(Node *)malloc(sizeof(Node));//申请头结点
	if(p==NULL)
		return ERROR;
	p->next=NULL;
	*aptr=p;
	return OK;
}

2.插入新节点(实现新建联系人功能)

  第一步:申请一个新结点用于记录新联系人的信息

                   使用malloc函数,需要强制转换。

  第二步:将这个新结点插入到链表的最后

                   新申请一个tmp指针指向tmp头结点,用while语句是tmp指针后移,直到链表尾部,即tmp->next的值为NULL时,进行                如下操作:

                   将tmp指向新申请的结点,新节点的指针域指向NULL。

Status Insert(Address_list aptr,Elemtype e[],Elemtype f[])
{
	Node *p=(Node *)malloc(sizeof(Node));
	if(p==NULL)
	{
		printf("堆空间已满\n");
		return ERROR;
	}
	strcpy(p->name,e);
	strcpy(p->tel,f);
	Address_list tmp=aptr;
	while(tmp->next!=NULL)
	{	
		tmp=tmp->next;
		if(strcmp(e,tmp->name)==0)
		{
			printf("此联系人已存在!\n");
			return ERROR;
		}
	}
	p->next=NULL;
	tmp->next=p;
	return OK;
}

4.删除结点(删除联系人)

  第一步:找到需要删除的结点

                 使用strcmp函数将需要删除联系人姓名与链表结点中数据依次对比,相同则执行第二步删除工作,不同与下一个结点对比,若是到链表结尾依然没有找到,则代表该联系人不存在。

  第二步:删除该结点

Status Delete(Address_list aptr,Elemtype e[],Elemtype f[])   
{
	Address_list tmp=aptr;
	
	while(1)
	{
		if(strcmp(e,tmp->next->name)==0)
			break;
		if(tmp->next->next==NULL&&strcmp(e,tmp->next->name)!=0)
		{
			printf("此联系人不存在!\n");
			return ERROR;
		}
		tmp=tmp->next;
	}
	Node *tmp2=tmp->next;
	strcpy(e,tmp2->name);
	strcpy(f,tmp2->tel);
	tmp->next=tmp2->next;
	free(tmp2);
	return OK;
}

5.查找联系人

   查找与上文删除联系人的第一步相同,使用strcmp函数即可,然后将该结点信息打印,较为简单。

Status Find(Address_list aptr,Elemtype e[],Elemtype f[])
{
	Address_list tmp=aptr;
	while(1)
	{
		if(strcmp(e,tmp->next->name)==0)
			break;
		if(tmp->next->next==NULL&&strcmp(e,tmp->next->name)!=0)
		{
			printf("此联系人不存在!\n");
			return ERROR;
		}
		tmp=tmp->next;
	}
	strcpy(f,tmp->next->tel);
	return OK;
}

6.按联系人姓名修改号码

    第一步:找到该结点,同上文查找

    第二步:修改信息,用strcpy函数将修改后的号码赋值给该结点的Tel域

Status Modify(Address_list aptr,Elemtype e[],Elemtype f[])
{
	Address_list tmp=aptr;
	while(1)
	{
		if(strcmp(e,tmp->next->name)==0)
			break;
		if(tmp->next->next==NULL&&strcmp(e,tmp->next->name)!=0)
		{
			printf("此联系人不存在!\n");
			return ERROR;
		}
		tmp=tmp->next;
	}
	strcpy(tmp->next->tel,f);
	return OK;
}

7.打印函数

Status Printlist(Address_list aptr)
{
	Address_list tmp=aptr;
	if(NULL==tmp)
	{
		printf("此表为空!\n");
		return ERROR;
	}
	else
	{
		while(tmp!=NULL)
		{
			printf("%-10s",tmp->name);
			printf("%s",tmp->tel);
			printf("\n");
			tmp=tmp->next;
		}
		printf("\n");
		return OK;
	}
}

8.将联系人按首字母排序

   第一步:申请一个指针数组用于依次指向链表的每一个结点

   第二步:将指针数组的内容进行排序

   第三步:打印指针数组的内容

Status Sort(Address_list aptr)
{
	int m=0;
	Address_list tmp=aptr;
	Node *a[100];
	tmp=tmp->next;
	while(tmp!=NULL)
	{
		a[m]=tmp;
		m++;
		tmp=tmp->next;
	}
	int i;
	for(i=0;i<m-1;i++)
	{
		int j;
		for(j=0;j<=m-2-i;j++)
		{
			if(strcmp(a[j]->name,a[j+1]->name)>0)
			{
				Node *tmp;
				tmp=a[j];
				a[j]=a[j+1];
				a[j+1]=tmp;
			}
		}
	}
	for(i=0;i<m;i++)
	{
		printf("%-10s",a[i]->name);
		printf("%s",a[i]->tel);
		printf("\n");
	}
	return OK;
}

9.将通讯录的联系人信息保存到另一个TXT文件中

   第一步:创建新的TXT文件

   第二步:将链表信息逐个写入TXT文件中,用fwrite函数

Status Fwrite(Address_list aptr)
{
	FILE *file=fopen("test5.txt","w+");
		if(NULL==file)
		{
			perror("fopen");
			return ERROR;
		}
	Address_list tmp=aptr;
	tmp=tmp->next;
	while(tmp!=NULL)
	{
		int count1=fwrite(tmp,sizeof(Node),1,file);
		if(EOF==count1)
		{
			perror("fwrite");
			fclose(file);
			return ERROR;
		}
		tmp=tmp->next;
	}
	
	return OK;
}

10.读取TXT文件中的联系人信息

     第一步:打开存有联系人信息的TXT文件

     第二步:逐个读取联系人信息,用fread函数

Status Fread(Address_list aptr)
{
	Address_list tmp=aptr;
	FILE *file=fopen("test5.txt","a+");
		if(NULL==file)
		{
			perror("fopen");
			return ERROR;
		}
	fseek(file,0,SEEK_SET);
	Node *p=(Node *)malloc(sizeof(Node));
	while(fread(p,sizeof(Node),1,file)!=0)
	{
		p->next=NULL;
		tmp->next=p;
		tmp=tmp->next;
		p=(Node *)malloc(sizeof(Node));
	}
	free(p);
	return OK;
}

11.主函数

  在主函数中引用上面写好的各个函数,再用一个switch函数实现执行时的供能选择。

int main()
{
	Address_list Ltop;
	Initaddress(&Ltop);
	//Insert(Ltop,"yu","13327829295");
	Fread(Ltop);
	Printlist(Ltop);
	Elemtype name[10];
	Elemtype tel[12];
	while(1)
	{
		int i;
		printf("\t\t\t1.查看通讯录\n");
		printf("\t\t\t2.新建联系人\n");
		printf("\t\t\t3.删除联系人\n");
		printf("\t\t\t4.查找联系人\n");
		printf("\t\t\t5.按联系人修改号码\n");
		printf("\t\t\t6.按联系人姓名排序\n");
		printf("\t\t\t0.终止程序\n");
		scanf("%d",&i);
		switch(i)
		{
			case 1:
				Printlist(Ltop);
				break;
			case 2:
				do
				{
					printf("请输入新建联系人的姓名\n");
					scanf("%s",name);
					printf("请输入新建联系人的手机号\n");
					scanf("%s",tel);
				}
				while(!Insert(Ltop,name,tel));
				Fwrite(Ltop);
				break;
			case 3:
				do
				{
					printf("请输入删除联系人的姓名\n");
					scanf("%s",name);
				}
				while(!Delete(Ltop,name,tel));
				printf("删除的联系人为:%s 号码为%s\n",name,tel);
				Fwrite(Ltop);
				break;
			case 4:
				do
				{
					printf("请输入查找联系人的姓名\n");
					scanf("%s",name);
				}
				while(!Find(Ltop,name,tel));
				printf("%s的号码为:%s\n",name,tel);
				break;
			case 5:
				do
				{
					printf("请输入要修改号码的联系人姓名\n");
					scanf("%s",name);
				}
				while(!Modify(Ltop,name,tel));
				printf("请输入修改后的号码:\n");
				scanf("%s",tel);
				Modify(Ltop,name,tel);
				printf("修改后%s的号码为:%s\n",name,tel);
				Fwrite(Ltop);
				break;
			case 6:
				Sort(Ltop);
				break;
			case 0:
				return 0;
			default:
				printf("输入选项有误\n");
				break;
		}
	}
	return 0;
}

通讯录项目至此结束。

猜你喜欢

转载自blog.csdn.net/ShiHongYu_/article/details/81081293