天天看点

Project2——链表实现的通讯录2.0

//带表头结点的链表
//链表实现通讯录,具备查询、删除、修改、添加、显示、排序等功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAL_OK 1
#define MAL_ERR 0

struct node
{
	char name[20];
    int num;
    struct node * next;
};

typedef struct node Node;
typedef struct node * Link;

void creat_link(Link * head);                       
void creat_node(Link * new_node, int i);           
int  judge_node(Link new_node);                    
void insert_node_head(Link new_node, Link head); 	
void insert_node_tail(Link new_node, Link head);  	
void insert_node_mid(Link new_node, Link head, int num_loc);  
void delete_node(Link head, int num_del);           
void display(Link head);                           
void release_link(Link * head);
void makempty_link(Link * head);


void address_initial(Link * head, Link new_node);   //初始化通讯录
void address_inquire(Link head);                    //查询联系人     
void address_delete(Link head);                     //删除联系人
void address_modify(Link head);                     //修改联系人
void address_add(Link head);                        //添加联系人
void user_interface(Link head);
int namecmp(char * p,char * q);
void address_sort(Link head);			  		//联系人排序
void swap(Link p, Link min);

int main()
{
    Link head = NULL;                              
    Link new_node = NULL;                           
    char n;

	address_initial(&head,new_node); 	 		
	while(1)
	{	
		user_interface(head);
		printf("请输入操作代号\n");
		scanf("%c",&n);
        getchar();
        if (n == 'G')
            break;
		switch(n)
		{
			case 'A': address_inquire(head);break;
			case 'B': address_delete(head);break;
			case 'C': address_modify(head);break;
			case 'D': address_add(head);break;
            case 'E': display(head);break;
			case 'F': address_sort(head);break;
            default :printf("error\n");
		}
        printf("\n\n\n\n\n\n");
	}
	
    release_link(&head);
	printf("链表通讯录关闭\n");
    display(head);
    return 0;
}


void user_interface(Link head)
{
	printf("**********************************************Adress System************************************************\n");
	printf("*** A.查询联系人  B.删除联系人  C.修改联系人  D.添加联系人  E.显示所有联系人  F.通讯录排序  G.退出      ***\n");
	printf("***                                                                                                     ***\n");
	printf("***********************************************************************************************************\n");
}
void address_initial(Link * head, Link new_node)
{
    int i;
	creat_link(head);                              //创建链表,此处为带表头结点的空链表
    for (i = 0;i < 5;i++)
    {
        creat_node(&new_node,i);                    
        insert_node_tail(new_node,*head);            
    }	
}

void address_inquire(Link head)
{
	printf("------------------------------------------------------------\n");   
    char * s, a;
    s = (char *)malloc(20*sizeof(char));		//给字符型指针赋初值
    Link p = head->next;
	
	printf("是否记得其全名?A.是 B.否\n");
	scanf("%c",&a);
	getchar();
	if (a == 'A')
	{	
		printf("请输入待查询人全名(中间以空格分开):\n");
		gets(s);
		//getchar();				//清空键盘输入缓存
		while (strcmp(p->name,s) != 0 && (p->next != NULL))
			p = p->next;
		if (p->next == NULL && strcmp(p->name,s) != 0)
			printf("查无此人\n");
		else
		{
			printf("该联系人的信息如下:\n");
			printf("姓名:%s\n",p->name);
			printf("电话号码:%d\n",p->num);
		}   
	}
	else
	{
		printf("请输入待查询人的名或姓\n");
		scanf("%s",s);
		getchar();	
		while (namecmp(p->name,s) != 0 && (p->next != NULL))
			p = p->next;
		if (p->next == NULL && namecmp(p->name,s) != 0)
			printf("查无此人\n");
		else
		{
			printf("该联系人的信息如下:\n");
			printf("姓名:%s\n",p->name);
			printf("电话号码:%d\n",p->num);
		}   
	}	
	
	printf("------------------------------------------------------------\n");   
}

void address_delete(Link head)
{
    printf("------------------------------------------------------------\n");   
	char * s, a;
    s = (char *)malloc(10*sizeof(char));
    Link p, q;
    p = head->next;
    q = head;
	
	printf("是否记得其全名?A.是 B.否\n");
	scanf("%c",&a);
	getchar();
	if (a == 'A')
	{	
		printf("请输入待删除人的全名(中间以空格分开):\n");
		gets(s);
		while (strcmp(p->name,s) != 0 && (p->next != NULL))
		{
			q = p;
			p = p->next;
		}
		if (p->next == NULL && strcmp(p->name,s) != 0)
			printf("查无此人\n");
		else
		{
			q->next = p->next;
			free(p);
			printf("修改后的通讯录如下:\n");
			display(head);
		}   
	}
	else
	{
		printf("请输入待删除人的名或姓\n");
		scanf("%s",s);
		getchar();	
		while (namecmp(p->name,s) != 0 && (p->next != NULL))
		{	
			q = p;
			p = p->next;
		}
		if (p->next == NULL && namecmp(p->name,s) != 0)
			printf("查无此人\n");
		else
		{
			q->next = p->next;
			free(p);
			printf("修改后的通讯录如下:\n");
			display(head);
		}   
	}	
	printf("------------------------------------------------------------\n");   
}

void address_modify(Link head)
{ 
	printf("------------------------------------------------------------\n");   
    long int i;
    char * s, a;
    s = (char *)malloc(10*sizeof(char));
    Link p, q;
    p = q = head->next;
	
	printf("是否记得其全名?A.是 B.否\n");
	scanf("%c",&a);
	getchar();
	
	if (a == 'A')
	{	
		printf("请输入待修改人的名字(中间以空格分开):\n");
		gets(s);
		while (strcmp(p->name,s) != 0 && (p->next != NULL))
		{
			q = p;
			p = p->next;
		}
		if (p->next == NULL && strcmp(p->name,s) != 0)
			printf("查无此人!\n");
		else
		{
			printf("输入修改后的号码:\n");
			scanf("%d",&i);
			getchar();
			p->num = i;
			printf("修改后的通讯录如下:\n");
			display(head);
		}
	}
	else
	{
		printf("请输入待删除人的名或姓\n");
		scanf("%s",s);
		getchar();	
		while (namecmp(p->name,s) != 0 && (p->next != NULL))
		{	
			q = p;
			p = p->next;
		}
		if (p->next == NULL && namecmp(p->name,s) != 0)
			printf("查无此人\n");
		else
		{
			printf("输入修改后的号码:\n");
			scanf("%d",&i);
			getchar();
			p->num = i;
			printf("修改后的通讯录如下:\n");
			display(head);
		}   
	}
	printf("------------------------------------------------------------\n");   
}

void address_add(Link head)
{
	printf("------------------------------------------------------------\n");   
    Link new_node;
    int i;
    char * s;
    s = (char *)malloc(10*sizeof(char));
    printf("输入待添加联系人的名字(注意:姓和名之间用空格隔开):\n");
    gets(s);

    printf("输入待联系人的电话号码:\n");
    scanf("%d",&i);
    getchar();
    
    new_node = (Link)malloc(sizeof(Node));
    new_node->num = i;
    strcpy(new_node->name, s);
    insert_node_tail(new_node, head);
    printf("添加后的通讯录如下:\n");
	display(head);
	printf("------------------------------------------------------------\n");   
}

void address_sort(Link head)
{
    Link p = head->next;
    Link min = p;
	Link q = head->next;
	while(p->next)
	{
        q = p->next;
		min = p;
		
        while(q)
		{
			if(strcmp(q->name,min->name) < 0)
			{
			   min = q;
			}
			q = q->next;
		}
		swap(p, min);  //这里很关键,如何交换两个节点的值,而不改变节点的指针指向?
		p = p->next;
	}
	printf("整理后的通讯录为:\n");
	display(head);
}

void swap(Link p, Link q)
{
	 Node temp = *p;
     temp.next = q->next;
     q->next = p->next;
     *p = *q;		//注意注意
	 *q = temp; 	//注意注意
}








//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

int namecmp(char * p,char * q)
{
	int i,j,flag = 1;	//flag = 表示名字不匹配
	for (i = 0;i < strlen(p);i++)
	{
		if (*(p+i) == *(q) && *(p+i+1) == *(q+1))
		{
			for(j = 0;j < strlen(q);i++,j++)
			{
				if (*(p+i) != *(q+j))
				{
					flag = 1;
					break;
				}
			}
			if (j == strlen(q))
				flag = 0;
		}
	}
	return flag;
}



void creat_link(Link * head)                        //二级指针适用于希望修改指针变量内容的场合
{
    Link new_node;
    new_node = (Link)malloc(sizeof(Node));
    new_node->num = 2018;
    strcpy(new_node->name,"node_head");
    *head = new_node;
    new_node->next = NULL;
}

int judge_node(Link new_node)                      //一级指针适用于只读指针内容的场合
{
    if (new_node == NULL)
        return MAL_ERR;
    else 
        return MAL_OK;
}

void creat_node(Link * new_node, int i)             //创建结点包括申请内存分配和给num赋值
{
	char * name[5] = {"Tom Cruise","Lebron James","Kobe Byrant","Fat Chou","Hao Yu"};
	int num[5] = {85850660,85417863,85416756,85573153,85159648};
    do
    {
        *new_node = (Link)malloc(sizeof(Node));
    }while(judge_node(*new_node) == MAL_ERR);
    strcpy((*new_node)->name,name[i]);
    (*new_node)->num = num[i];
}

void insert_node_head(Link  new_node, Link  head) //头插结点,把新结点的指针域指向头指针
{
    new_node->next = head->next;                        //新结点的指针域指向头指针
    head->next = new_node;                              //头指针指向新结点
}

void insert_node_tail(Link new_node, Link head)   //尾插结点
{
    Link p;                                         //定义一个struct node型的指针
    p = head;
    while(p->next != NULL)                      //链表只能用顺序访问的方法
        p = p->next;
    p->next = new_node;                         //如果p的指针域指向NULL,那么p就是末尾结点,在该结点后插入
    new_node->next = NULL;
}

void insert_node_mid(Link new_node, Link head, int num_loc)//中插(前插)
{
    Link p,q;
    p = q =head; 
    
    while(p->num != num_loc && p->next != NULL) 
    {                                           
        q = p;                                   
        p = p->next;                            
    }
    
    if(p->next == NULL && p->num != num_loc )   
    {
        p->next = new_node;
        new_node->next = NULL;
    }
    else                                            
    {
        q->next = new_node;
        new_node->next = p;
    }
}

void delete_node(Link head, int num_del)          //删除结点
{
    Link p,q;
    p = q = head;
    while(p->num != num_del && p->next != NULL) 
    {
        q = p;                                  
        p = p->next;                            
    }

        if(p->next == NULL && p->num != num_del)

            printf("ERROR\n");
        else                                  
        {
            q->next = p->next;
            free(p);
        }
}

void display(Link head)
{
    Link p;
    int i = 0;
    p = head;
    if (p == NULL)
        printf("链表已被释放\n");
    else if(p->next == NULL)
        printf("链表已被清空\n");
    else
    {
        p = p->next;
        while(p != NULL)
        {
            i++;
            if (p != NULL)
            {
                printf("第%d个联系人:\n",i);
                printf("//姓名:%s\n",p->name);
                printf("//电话号码:%d\n",p->num);
            }
            p = p->next;
        }
    }
}

void makempty_link(Link *head)
{
    Link p, q;
    p = (*head)->next;
    if (*head == NULL)
        printf("Link is null!!!!!!!\n");
    else 
    {   
        while(p != NULL)
        {
            q = p;
            free(p);
            p = q->next;
        }
        (*head)->next = NULL;
    }
}

void release_link(Link *head)
{
    Link p, q;
    p = *head;
    if (*head == NULL)
        printf("Link is empty!!!!!!!\n");
    else 
    {   
        while(p != NULL)
        {
            free(p);
            p = p->next;
        }
    }
    *head = NULL;
}
           

继续阅读