链表通讯录

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 20
/*定义结构体,保存通讯录中每个联系人的信息,person为节点类型,linkman为指向

   person类型节点的指针类型*/

typedef struct node
{
    char name[MAXSIZE];
    char phone[MAXSIZE];
    struct node *next;        /*存放后继元素地址*/
}person,*linkman;

/*定义一个枚举*/
enum sel
{
    EXIT,
    CREATE,
    ADD,
    DELETE,
    SEARCH,
    MODIFY,
    SHOW,
    SAVE,
    CLEAR

};


/*初始化一个单链表,创建一个通讯录*/
linkman Init_person()
{
    linkman Head;               /*定义一个头节点*/
    Head = (linkman)malloc(sizeof(person));
    if(Head)
    {
        Head->next = NULL;
    }
    printf("通讯录创建成功!\n请添加联系人!\n");
    return Head;

}


/*求链表的长度*/
int length_person(linkman Head)
{
    linkman p = Head;        /*p指向头节点*/
    int count = -1;          /*用于计算链表的长度*/
    while(p)
    {
        p = p->next;         /*遍历链表*/
        count++;
    }
    return count;           /*返回链表的长度*/


/*查找i个节点*/
linkman locate_person_pos(linkman Head,int i)
{
    linkman p;
    int j;
    p = Head;                 /*p指向头节点*/
    j = 0;
    while(p && j < i)        /*查找第i个节点*/
    {
        p = p->next;
        j++;
    }
    if((j != i) || !p)
    {
        return NULL;
    }                         /*第i个节点不存在*/
    return p;                 /*返回第i个节点*/

}


/*通过姓名查找的指定联系人所在节点的位置*/
int locate_person(linkman Head,char *dname)  
{
    int count = 0;            /*用于计数*/
    linkman p = Head;         /*p指向头节点*/
    while(p)
    {
        if(strcmp(p->name,dname) == 0)     
        {
           break;
        }
        else
        {
            p = p->next;
            count++;
        }
    }
    return count;           /*返回指定联系人所在位置*/   
}

/*添加联系人*/

int insert_person(linkman Head,int i,char *name,char *phone)

{
    linkman p;
    linkman q;
    p = locate_person_pos(Head,i-1);     /*p指向第i-1个节点*/
    if(!p)
    {
        printf("i error!\n");
        return 0;
    }
    q = (linkman)malloc(sizeof(person));  
    if(!q)
    {
        printf("fail to apply for space!");
        return 0;
    }
    strcpy(q->name,name);               /*给节点赋值*/
    strcpy(q->phone,phone);
    q->next = p->next;
    p->next = q;
    return 1;
}

/*将联系人按照姓名进行排序*/
linkman sort_person(linkman Head)
{
    linkman p;
    linkman q;
    char temp[MAXSIZE];        /*定义两个中间字符数组*/
    char temp2[MAXSIZE];
    for(p = Head;p->next != NULL;p = p->next)  
    {
        for(q = Head; q->next != NULL; q= q->next)
        {
            if(strcmp(q->name,q->next->name)>0) /*比较大小,交换节点信息*/
            {
                strcpy(temp,q->name);
                strcpy(q->name,q->next->name);
                strcpy(q->next->name,temp);
                strcpy(temp2,q->phone);
                strcpy(q->phone,q->next->phone);
                strcpy(q->next->phone,temp2);

/*将数组清空*/
                memset(temp,0,MAXSIZE);              
                memset(temp2,0,MAXSIZE);
            }
        }
    }
    return Head;            /*返回头节点*/
}

/*遍历链表统计同名联系人的个数*/
int search(linkman Head,char *dname)
{
    linkman p;
    int count = 0;               /*用于计数*/
    p = Head;                   /*p指向头节点*/
    while(p != NULL)
    {
        if(strcmp(dname,p->name) == 0)
        {
   count++;
        }
p = p->next;
    } 
    return count;
}

/*查找指点联系人的信息*/
int search_person(linkman Head,char *sname)
{
    linkman p;
    int count = 0;

    p = Head;                   /*p指向头节点*/


    /*遍历查找指定联系人*/
    while(p != NULL)
    {
        if(strcmp(sname,p->name) == 0)
        {
            /*打印指定联系人的信息*/
            printf("name:%s\tphone:%s\t\n",p->name,p->phone);
   count++;
        }
p = p->next;
    } 
    if(count == 0)
    {
        printf("该联系人不存在!\n");
    }
    return 1;


/*删除指定联系人*/
int delete_person(linkman Head,char *dname)
{
    int count;
    int location;  /*接指定联系人的位置*/
    int i;
    linkman p;
    linkman q;
    if(Head == NULL || Head->next == NULL)
    {
        printf("该通讯录不存在!\n");
        return 0;
    }
    count = search(Head,dname); 
    /*判断是否有同名的联系人,如果有,择删除指定的同名联系人*/
    if(count >= 2)
    {
        search_person(Head,dname);
printf("请选择要删除第几个人:\n");
scanf("%d",&i);
getchar();
while(i > count || i < 1)
{
   printf("输入错误,请重新选择!\n");
   scanf("%d",&i);
   getchar();
}
location = locate_person(Head,dname);
p = locate_person_pos(Head,location + (i - 1) -1);
    }
    /*若无同名联系人,则删除该联系人*/
    else
    {
        location = locate_person(Head,dname);
        /*找到指定联系人的位置*/

        /*p指向指定联系人的上一个节点位置*/
        p = locate_person_pos(Head,location-1);
    }
    if(p == NULL || p->next == NULL)
    {
        printf("该联系人不存在!\n");
        return 0;
    }
    q = p->next;
    p->next = q->next;
    free(q);                            /*释放指定联系人的节点*/
    printf("删除联系人成功!\n");
    return 1;
}          

/*修改联系人信息*/
int modify_person(linkman Head,char *mname)
{
    int count;     
    int location;  /*接指定联系人的位置*/
    int i;
    char nphone[MAXSIZE];
    char nname[MAXSIZE];
    linkman p;
    if(Head == NULL || Head->next == NULL)
    {
        printf("该通讯录不存在!\n");
        return 0;
    }
    count = search(Head,mname);
    /*判断是否有同名的联系人,如果有,择修改指定的同名联系人*/
    if(count >= 2)
    {
        search_person(Head,mname);
printf("请选择要修改第几个人的信息:\n");
scanf("%d",&i);
getchar();
while(i > count || i < 1)
{
   printf("输入错误,请重新选择!\n");
   scanf("%d",&i);
   getchar();
}
location = locate_person(Head,mname);
p = locate_person_pos(Head,location + (i -1));
    }
    /*若无同名联系人,则修改该联系人信息*/
    else
    {
        location = locate_person(Head,mname);
        /*找到指定联系人的位置*/

        /*p指向指定联系人的节点位置*/
        p = locate_person_pos(Head,location);
    }
    if(p == NULL)
    {
        printf("该联系人不存在!\n");
        return 0;
    }
    printf("请输入修改联系人的新姓名:\n");
    scanf("%s",nname);
    printf("请输入修改联系人的新号码:\n");
    scanf("%s",nphone);
    strcpy(p->name,nname);
    strcpy(p->phone,nphone);
    printf("修改联系人成功!\n");
    return 1;
}

/*释放所有节点*/
void free_person(linkman *Head)
{
    linkman p;
    linkman q;
    p = *Head;
    while(p)         /*释放链表的所有节点*/
    {
        q = p;
p = p->next;
        free(q);
    }
    *Head = NULL;

}


/*清空所有联系人*/
void clear_person(linkman *Head)
{
    FILE *fp;
    linkman p;
    linkman q;
    p = (*Head)->next;        /*保留头节点*/

    /*清空保存在文件中的联系人信息*/
    fp = fopen("telephone.txt","w");
    if(NULL == fp)
    {
        printf("open file fail!\n");
exit(1);
    }
    fclose(fp);
    /*释放除头节点外的所有节点*/
    while(p)
    {
        q = p;
p = p->next;
free(q);
    }
    (*Head)->next = NULL;
    printf("清除所有联系人成功!\n");
}

/*打印所有联系人的信息*/
void show_person(linkman Head)
{
    linkman p = Head->next;   /*p指向头节点的下一个节点*/
    if(NULL == Head->next)
    {
        printf("暂无联系人,请添加联系人!\n");
    }
    /*遍历打印节点信息*/
    while(p)
    {
        printf("name:%s\tphone:%s\t\n",p->name,p->phone);
        p = p->next;
    }
    printf("\n");

}


/*将所有联系人保存在指定文件中*/
void save_person(linkman Head)
{
    FILE * fp;
    linkman p;
    fp = fopen("telephone.txt","w");     /*打开文件*/
    if(NULL == fp)
    {
        printf("open file fail!\n");
        exit(1);
    }
    p = Head;                   /*p指向头节点*/
    while(p != NULL)           /*遍历所有节点*/
    {
        fwrite(p,sizeof(person),1,fp);/*将一个节点大小的内容写入文件中*/
        p = p->next;
    }
    fclose(fp);                     /*关闭文件*/
    printf("保存成功!\n");
}

/*从指定文件中读取联系人信息*/
linkman read_person()
{

    FILE *fp;


    linkman t1;
    linkman t2;

    linkman Head;        /*定义一个头节点*/


    char ch;

    int read;

    fp = fopen("telephone.txt","a+");   /*打开文件*/
    if(NULL == fp)
    {
        printf("open file fail!\n");
        exit(1);
    }

    fseek(fp,0,SEEK_SET);

    ch = fgetc(fp);               /*判断该文件是否为空*/
    if(EOF == ch)
    {
        printf("该通讯录不存在!\n请先创建通讯录!\n");
        return Head;
    }
    else
    {
        fseek(fp,0,SEEK_SET);
    }
    t1 = (linkman)malloc(sizeof(person));
    Head = t1;
    while(!feof(fp))
    {
       /*将文件中的一个节点大小的信息写入链表的节点中*/
        read = fread(t1,sizeof(person),1,fp);
if(read != 1)
{
   break;
}
        t1->next = (linkman)malloc(sizeof(person));
        t2 = t1;
        t1 = t1->next;
    }
    t2->next=NULL;
    free(t1);                 /*将多余的一个节点释放*/
    fclose(fp);               /*关闭文件*/
    printf("读取通讯录成功!\n");
    return Head;              /*返回头节点*/
}

/*菜单目录*/
void menu()
{
    printf("****************************\n");
    printf("    欢迎使用通讯录\n");
    printf("1.  创建通讯录\n");
    printf("2.  添加联系人\n");
    printf("3.  删除指定联系人\n");
    printf("4.  查找指定联系人\n");
    printf("5.  修改指定联系人信息\n");
    printf("6.  显示所有联系人\n");
    printf("7.  保存所有联系人\n");
    printf("8.  清空所有联系人\n");
    printf("0.  退出通讯录\n");
    printf("***************************\n");
}

int main()
{
    linkman Head;             /*定义头节点*/
    int sel;
    char name[MAXSIZE];
    char phone[MAXSIZE];
    char dname[MAXSIZE];
    char sname[MAXSIZE];
    char mname[MAXSIZE];

    Head = read_person();      /*读取文件中的联系人信息*/
    while(1)
    {
        menu();
printf("请选择:\n");
        scanf("%d",&sel);
getchar();
        switch(sel)
        {
            case CREATE:
            {
                Head = Init_person();
                break;
            }
            case ADD:
            {
                printf("请输入姓名:\n");
                scanf("%s",name);
                printf("请输入电话号码:\n");
                scanf("%s",phone);
                insert_person(Head,length_person(Head)+1,name,phone);
sort_person(Head);
                break;
            }
            case DELETE:
            {
                printf("请输入要删除的联系人姓名:\n");
                scanf("%s",dname);
                delete_person(Head,dname);
                break;
            }
            case SEARCH:
            {
       
                printf("请输入姓名:\n");
                scanf("%s",sname);
                search_person(Head,sname);
                break;
            }
   case MODIFY:
   {
       
                printf("请输入要修改的联系人姓名:\n");
                scanf("%s",mname);
                modify_person(Head,mname);
sort_person(Head);
                break;
   }
            case SHOW:
            {
                show_person(Head);
                break;
            }
            case SAVE:
            {
               save_person(Head);
               break;
            }
   case CLEAR:
   {
       clear_person(&Head);
       break;
   }
            case EXIT:
            {
       free_person(&Head);
                return 0;
                break;
            }
   default:
   {
       printf("输入错误!\n请重新输入!\n");
break;
   }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值