c语言基础 通讯录(基于单链表版的)保存信息版

发布于:2023-01-23 ⋅ 阅读:(496) ⋅ 点赞:(0)

目录

一 总览

思路: 

1.1main.c文件

1.2 tongxunlu.h

三 tongxunlu.c

1.创建空链表

2.菜单

3.switch  case  调用函数

4.判断链表是否为空

5.添加联系人

6.查看所有联系人

7.查找联系人

8.删除联系人

9.修改联系人信息

10 结束整个进程

11.writetxt  将改动后的单链表写入txt

12.将txt文件内容读入单链表

13.单链表的整表删除函数


一 总览

思路: 

                基于上个版本 对联系人进行删除  修改信息等;整体多了两个函数

第一个 writetxt 将txt文件清空  并将修改过单链表(包括删除联系人等)整体写入 txt 文件

基于上个版本只用将writetxt函数加在修改信息代码段之后

第二个 readtxt2   运行程序开始第一不  创建空的链表  并将txt文件的数据(联系人)并按首字母排序读入链表中;

1.1main.c文件

#include "tongxunlu.h"


int main(int argc, char const *argv[])
{
    tongxunlist *head = tongxunlistcreate();
    readtxt2(head);//将txt文件里的 联系人信息按首字母大小排序并读入单链表中
        while (1)//这个循环可以实现 功能结束返回菜单
    {
        menu(); //菜单  
        myswitch(head); //这里在tongxunlu.c封装好了也可直接在main.c里写
    }
    return 0;
}

1.2 tongxunlu.h

#ifndef _TONGXUNLU_h
#define _TONGXUNLU_H
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
typedef int datatype;

typedef struct tongxunlu
{
    char name[32];//姓名

    datatype age; //年龄

    char adress[32];//住址

    char tel[32];//电话

    struct tongxunlu *next;  //指针域
    
}tongxunlist;


tongxunlist* tongxunlistcreate();
//mymenu 菜单
void menu();

void myswitch();

//mystrncmp  
int my_strncmp(const char *str,const char *str1,int n);

//判断链表是否为空
int tongxunempty(tongxunlist *head);

//my_strcmp
int my_strcmp(char *str,char *str1);

//直接插入排序
void linklist_straight_insertion(tongxunlist *head);

//单链表的遍历
void linklistprintf(tongxunlist *head);

//查找联系人
void Find_person(tongxunlist *head);

//删除联系人
void  del_person(tongxunlist *head);

//修改联系人信息
void  tongxunlistdata_data(tongxunlist *head);

//结束进程
void endp();

//txt文件读取至单链表
//void readtxt(tongxunlist *head);

//将修改过的链表存入txt文件
void writetxt(tongxunlist *head);
//从文件中读取数据并排序放入链表
void readtxt2(tongxunlist *head);

//单链表的整表删除
void linklist_all_delete(tongxunlist *head);

#endif

三 tongxunlu.c

1.创建空链表

tongxunlist* tongxunlistcreate()
{
    tongxunlist *head = (tongxunlist *)malloc(sizeof(tongxunlist));
    head->next = NULL;
    return head;
}

2.菜单


tongxunlist* tongxunlistcreate()
{
    tongxunlist *head = (tongxunlist *)malloc(sizeof(tongxunlist));
    head->next = NULL;
    return head;
}

//mymenu 菜单
void menu()
{   
    printf("**************欢迎使用通讯录*****************\n");
    printf("*********************************************\n");
    printf("**  1.添加联系人              2.查看联系人 **\n");
    printf("**  3.搜索联系人              4.删除联系人 **\n");
    printf("**  5.修改用户信息            6.退出通讯录 **\n");
    printf("*********************************************\n");
    printf("*********************************************\n");

}

3.switch  case  调用函数

void myswitch(tongxunlist *head)
{   
    int num;//定义整形 数字
    scanf("%d",&num); //输入数字 调用对应功能
    getchar();  //吞噬垃圾字符 防止出现错误
    while(1) //此处用循环可以为下面连续使用对应功能 
    {   
        switch (num)
        {             
            case 1:
            printf("正在添加联系人.....\n");
            putchar(10);//没什么作用为了让终端显示的不那么拥挤
            linklist_straight_insertion(head);//添加联系人函数调用
            break;
            case 2:
                printf("正在查看联系人.....\n");
                putchar(10);
                linklistprintf(head);//查看联系人函数调用
                break;
            case 3:
                printf("正在搜索联系人.....\n");
                Find_person(head);
                putchar(10);
                ;//搜索联系人函数调用
                break;
            case 4:
                printf("正在删除联系人.....\n");
                del_person(head);
                putchar(10);
                ;//删除联系人函数调用
                break;
            case 5:
                printf("正在修改联系人.....\n");
                putchar(10);
                tongxunlistdata_data(head);//修改联系人函数调用
                break;
            case 6:
                printf("正在退出通讯录.....\n");
                endp(head);//退出函数调用
                break;      
            default:
                printf("对不起您输入有误,请重新输入\n");
                return;
        }
        break;  
    }
}

4.判断链表是否为空

int tongxunempty(tongxunlist *head)
{
    if (head->next==NULL)
    {
    return  1 ;
    }
    else 
    {
    return 0;
    }
}

5.添加联系人

//添加联系人
void linklist_straight_insertion(tongxunlist *head)
{
    tongxunlist *tmp=(tongxunlist *)malloc(sizeof(tongxunlist));
    tmp->next=NULL;

    printf("请输入姓名:\n");
    scanf("%s",tmp->name); 

    printf("请输入年龄:\n");
    scanf("%d",&tmp->age);
    
    printf("请输入住址:\n");
    scanf("%s",tmp->adress);

    printf("请输入电话号码:\n");

    scanf("%s",tmp->tel);
    putchar(10);

    
    tongxunlist *p =head;//定义一个指针为表头
    //q=q->next;
    if(1==tongxunempty(head))
    {
        tmp->next=head->next;//令新插入的结点指针指向下一个结点
    //tmp 新插入结点的地址
        head->next=tmp;
    }
    else
    {
        while(p->next!=NULL&&my_strncmp(p->next->name , tmp->name,1)<0)//当目的name小于源name
        {
            p=p->next;
        }
        //当p->next指向的数据大于或者等于需要插入的数据是跳出循环
        //此事p->next  向的是第一个大于value的值
        tmp->next=p->next;
        p->next=tmp;  //然后将其插入大于value的值之前
        printf("*****联系人添加完成*****\n");
        putchar(10);
    }
    //将数据写入txt文本
    writetxt(head);

    int num = 0;  
    printf("*请选择是否继续添加联系人*\n");

    printf("*1.继续添加*    2.返回菜单*\n");
    scanf("%d",&num);
    getchar();
    if(num == 1)
    {
        linklist_straight_insertion(head);//继续添加就在此调用函数
    }  
    else
    {
        return ;       //不添加就结束 把程序流程从被调函数转向主调函数    main.c在此循环进入菜单              
    } 
}

6.查看所有联系人

//链表查看所有联系人
void linklistprintf(tongxunlist *head)
{
    //定义一个指针  遍历保存第一个有数据的结点
    tongxunlist *p = head->next;
    if(1==tongxunempty(head))
    {
        printf("该通讯录为空请添加联系人\n");
        printf("请进行添加联系人\n");
        return;
    }
    //循环遍历单链表,直到指针指为空结束循环 因为最后一个结点的指针域指向NULL
    while(p->next !=NULL)
    {
        printf("╔════════════════════════════════════════════════════════╗\n");
        printf("*姓名%s__年龄:%d___住址:%s__电话%s*\n",p->name,p->age,p->adress,p->tel);
        printf("╚════════════════════════════════════════════════════════╝\n");
    //p循环中指向下一个结点 
        p=p->next;
    }
        printf("╔════════════════════════════════════════════════════════╗\n");
        printf("*姓名%s__年龄:%d___住址:%s__电话%s*\n",p->name,p->age,p->adress,p->tel);
        printf("╚════════════════════════════════════════════════════════╝\n");
    putchar(10);
}

7.查找联系人

//查找联系人
void Find_person(tongxunlist *head)
{
    if(1==tongxunempty(head))
    {
        printf("该通讯录为空请添加联系人\n");
        printf("请进行添加联系人\n");
        return;
    }
    char s1[32]={0};//定义一个字符串数组 用于保存你输入想要查找联系人的名字
        printf("********************************\n");
        printf("请输入您所查找联系人的姓名或者住址\n");
        printf("********************************\n");
        int i;
        scanf("%s",s1);
        tongxunlist *p =head;
        while(p!=NULL)//如果用p->next!=NULL  当p在最后一个结点是 p->next=NULL 无法进入循环
        {   
            if(my_strcmp(s1,p->name) == 0 ) 
            {
                printf("╔═══════════════════════════════════════════════════════════╗\n");
                printf("* 姓名%s__年龄:%d___住址:%s__电话%s *\n",p->name,p->age,p->adress,p->tel);
                printf("╚═══════════════════════════════════════════════════════════╝\n");
                break;
            }
            else if(my_strcmp(s1,p->adress) == 0 )  //这个是按地址查询 道理与上面相同
            {
                printf("╔═══════════════════════════════════════════════════════════╗\n");
                printf("*姓名%s__年龄:%d___住址:%s__电话%s*\n",p->name,p->age,p->adress,p->tel);
                printf("╚═══════════════════════════════════════════════════════════╝\n");
                break;
            }
            p=p->next;
        }
            if(p==NULL)
            {
                printf("**查无此人**\n");
                putchar(10);
            }
            printf("请问是否要继续查询联系人\n");
            printf("**1.继续查找**      **2.返回菜单**\n");
            putchar(10);
            int num = 0;
            getchar();//吞噬垃圾字符
            scanf("%d",&num);
            if(num==1)
            {
                Find_person(head);//强行执行下次循环继续查找
            }
            else 
            {
                return;  //如果输入不为1 退出  进入主函数  在次循环进出菜单
            }
    
}

8.删除联系人

//删除联系人
void  del_person(tongxunlist *head)
{
    if(1==tongxunempty(head))
    {
        printf("该通讯录为空请添加联系人\n");
        printf("请进行添加联系人\n");
        return;
    }
    printf("**请输入你想删除联系人的名字**\n");
    char s2[32] = {0};
    scanf("%s",s2);
    tongxunlist *p = head;

    tongxunlist *q;

    while(p->next!=NULL)
    {
        if(my_strcmp(s2,p->next->name)==0)
        {
            q=p->next;
            p->next=p->next->next;
            free(q);
            q=NULL;
            printf("删除成功\n");
            writetxt(head);
            return;
        }
        p=p->next;
    }
}

9.修改联系人信息

//修改联系人信息
void  tongxunlistdata_data(tongxunlist *head)
{
    if(1==tongxunempty(head))
    {
        printf("该通讯录为空请添加联系人\n");
        printf("请进行添加联系人\n");
        return;
    }
    
    printf("**请输入您所要修改信息的人名**\n");
    char s3[32] = {0};
    scanf("%s",s3);
    tongxunlist *p=head;//定义一个指针指向头结点
    p=p->next;//头结点无数据  直接跳过
    while(p!=NULL)
    {
        if(my_strcmp(s3,p->name) == 0 ) 
        {
            
            printf("请输入新的姓名\n");//下面直接进行覆盖就行了
            scanf("%s",p->name);    //把新的信息覆盖旧的信息

            printf("请输入新的年龄\n");
            scanf("%d",&p->age);

            printf("请输入新的住址\n");
            scanf("%s",p->adress);

            printf("请输入新的电话\n");
            scanf("%s",p->tel);

            printf("修改成功\n");
            writetxt(head);//重新写入
            return;  //修改完  返回主函数 循环进入菜单
        }
        p=p->next;
    }
    
    if(p==NULL)
    {
        printf("**不存在该联系人**\n");
        putchar(10);
    }

}

10 结束整个进程

//结束整个进程
void endp(tongxunlist *head)

{
    linklist_all_delete(head);//内容已经保存至txt删除整个单链表
    exit(0);
}

11.writetxt  将改动后的单链表写入txt

//改动后的链表写入txt
void writetxt(tongxunlist *head)
{
    tongxunlist *q =head;
    //q=q->next;
    FILE *fp = fopen("./1.txt","w");
    if(NULL == fp)//失败返回NULL  成功返回文件流指针
    {
        perror("fopen");
        return ;
    }
    
    while(q->next!=NULL)
    {
        if(1 != fwrite(q->next,sizeof(tongxunlist),1,fp))//成功返回大小,失败返回个数
        {
            perror("fwrite");
            return ;
        }
        q=q->next;
    }
    fclose(fp);
    printf("链表写入文件...");
    putchar(10);
}

12.将txt文件内容读入单链表

//读取文件并将其排序存入链表
void readtxt2(tongxunlist *head)
{

        tongxunlist *p = head;

        FILE *fp = fopen("./1.txt","r");  //成功返回文件流指针  失败返回NULL
        if(NULL == fp)
        {   
            perror("fopen");
            return ;
        }
    
    while(0 == feof(fp))   //循环读取txt文件
    {
        
        tongxunlist *tmp=(tongxunlist *)malloc(sizeof(tongxunlist));
        tmp->next=NULL; 
        //将读取的数据  保存至tmp中
        if(0 == fread(tmp,sizeof(tongxunlist),1,fp))//成功返回个数  失败返回0
        {
            if(feof(fp))//达到文件末尾返回非0 其他返回0
            {
                
                printf("文件内容读入链表..\n");
                
                printf("正在进入菜单....\n");
                break;
            }
            else
            {
                perror("fread");
                return ;
            }
        }

//将按首字母大小插入单链表中
        if(1==tongxunempty(head))
        {
            tmp->next=head->next;//令新插入的结点指针指向下一个结点
                                 //tmp 新插入结点的地址
            head->next=tmp;
        }
        else
        {
            while(p->next!=NULL&&my_strncmp(p->next->name , tmp->name,1)<0)//当目的name小于源name
            {
                p=p->next;
            }
            //当p->next指向的数据大于或者等于需要插入的数据是跳出循环
            //此事p->next  就是插入的位置

            tmp->next=p->next;
            p->next=tmp; 
        }
        putchar(10);
    }
}

13.单链表的整表删除函数


//链表的整表删除
void linklist_all_delete(tongxunlist *head)
{
    if(tongxunempty(head))
    {
        printf("链表为空\n");
        return;
    }
    tongxunlist *p,*q;//定义两个指针
    q=NULL;     
    p=head->next;//令p相当于头结点指向第一个结点
    while(p!=NULL)
    {
        q=p;  //q相当于头结点 也指向第一个结点
        p=p->next; //p指向第二个结点
        free(q);  //q=head->next 释放第一个结点
    }
    head->next=NULL;//头结点 置空
    printf("整表释放成功....\n");
    
    return;

}
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到