素材巴巴 > 程序开发 >

简单易上手的通讯录实现,跟着敲,你也能拥有属于你的通讯录!(代码 笔记已经上传至gitee)

程序开发 2023-09-14 14:13:06

通讯录

老规矩笔记和代码欢迎自取~
链接:

  1. 通讯录笔记
  2. 通讯录工程文件+源代码

文章目录

  • 三、实现的代码步骤分析

  • 一、通讯录的组成

    利用最近所学的知识,试着实现一个通讯录

    手机里面的通讯录信息

    在这里插入图片描述

    最后我决定给通讯录增加以下信息


    二、通讯录文件构成

    为什么每一篇小项目都强调一遍文件构成?

    1. test.c

    按照之前的设计小游戏一样,test.c文件是必要的,用来测试各种功能使用是否可以正常使用或者运行

    还包括整个通讯录的框架,比如提供给使用者得选择菜单

    2. correspondence.c

    用来设计实现通讯录功能的文件,文件包含的基本上都是函数

    函数包括实现增加/删除/修改/查找/打印/排序联系人

    3. correspondence.h

    包含 test.c 和 correspondence.c 中需要用到的库函数的头文件,以及全过程需要使用的变量


    三、实现的代码步骤分析

    1. 打印菜单

    使用者上手即操作,我们需要提供给他们操作的菜单,也是我们功能的目录

    菜单明细上面也分析了,主要包含:

    void menu()//菜单
     {printf("==============通讯录=============n");printf("         1.添加联系人(add)       n");printf("         2.查找联系人(seek)      n");printf("         3.删除联系人(delete)    n");printf("         4.修改联系人(modify)    n");printf("         5.排序联系人(sort)      n");printf("         6.打印联系人(print)     n");printf("         0.退出通讯录(EXIT)      n");}
     

    利用最近所学的枚举类型,我们试着这次的循环内的switch语句,判断不选择数字,而选择判断功能的内容

    所以我们定义一个枚举类型,用单词代表各个功能

    此过程在 test.c 文件中

    enum menu
     {EXIT,//0add,//1seek,//2delete,//3modify,//4sort,//5print//6
     };
     

    把exit放前面正好代表0,每个枚举常量代表的数字都是对应的功能


    到此为止,整个循环的大概模型是这样,代码如下

    此过程在 test.c 文件中

    int main()
     {int input = 0;do{menu();//打印菜单提供使用者选择printf("请选择您要使用的功能(输入选项括号内内容):");scanf("%d", &input);//使用者输入选择switch (input){case add:break;case seek:break;case delete:break;case modify:break;case sort:break;case print:break;case exit:printf("您选择了退出通讯录n");break;default:printf("输入错误信息,请重新输入:n");break;}} while (input != 0);return 0;
     }
     

    运行的结果

    分别测试了 正确信息 错误信息 退出功能

    在这里插入图片描述


    2. 联系人信息初始化

    刚拿到新手机的大家,通讯录里面是没有联系人的信息

    但可以通过自己填写联系人信息存储到手机中

    我们需要提供给使用者,接收/存储信息的一个数据库

    但因为人的信息是复杂的,是多种元素构成

    信息包括:姓名 + 性别 + 年龄 + 电话 + 公司地址

    使用类型:char char int int char

    此过程在 correspondence.h 文件中

    #define NAME_MAX 11
     #define GENDER_MAX 5
     #define TELE_MAX 12
     #define EMAIL_MAX 20//通讯录初始化个人信息
     struct perinfmt //personal information
     {char name[NAME_MAX];//支持5个汉字(2个字节一个汉字)char gender[GENDER_MAX];//男性 or 女性int age;char tele[TELE_MAX];//11位电话号码char email[EMAIL_MAX];//19位邮箱
     };
     

    为了不用每次挨个修改个人信息的大小,我们用define定义每个信息的最大值


    还没有结束,我们创建好的是每个人的信息填写位置,但还没有创建一个通讯录,有100个人,每个人还需要标记序号(这里序号不放在个人信息里是因为,创建联系人的时候不会去填每个人的信息),这是需要我们系统内部自己去偷偷记录的

    此时100个人 + 序号 通讯录仍然是复杂信息 我们再次创建结构体变量

    此过程在 correspondence.h 文件中

    struct address_book //通讯录内容
     {struct perinfmt p[BOOK_MAX];//每个人信息,数组一共100个人int ID;//统计每个人编号
     };
     

    创建通讯录的结构体变量时,我们仍然还没有初始化

    新建一个函数,专门初始化它

    此过程在 correspondence.c 文件中

    void Initialize(struct address_book* ap)
     {ap->ID = 0;//序号初始值0memset(ap->p, 0, sizeof(ap->p));//初始化整个结构体数组大小为0}
     

    记得在 correspondence.h 中声明

    我们才能在 test.c 上使用 (记得在进入循环前就初始化好)

    struct address_book alinfmt;//all information
     Initialize(&alinfmt);//初始化通讯录
     

    PS:但其实也可以不创建这个 函数初始化

    (我们是为了方便,这样每次都可以,直接用函数初始化)

    可以在创建变量的时候直接初始化

    struct address_book alinfmt = { { 0 }, 0 };//all information
     

    此过程在 test.c 中完成


    3. 添加联系人

    功能的铺垫已经写好了

    我们开始写主要的功能

    添加联系人函数

    //增加联系人
     void add_contact(struct address_book* ap)
     {if (ap->ID == BOOK_MAX){printf("通讯录满了,请删除一些联系人再添加!n");}else{printf("请输入联系人姓名:");scanf("%s", ap->p[ap->ID].name);printf("请输入联系人性别:");scanf("%s", ap->p[ap->ID].gender);printf("请输入联系人年龄:");scanf("%d", &(ap->p[ap->ID].age));//这里是因为age是int类型变量需要传地址,其他数组类型变量名就是地址printf("请输入联系人电话:");scanf("%s", ap->p[ap->ID].tele);printf("请输入联系人邮箱地址:");scanf("%s", ap->p[ap->ID].email);printf("-----添加完成-----n");ap->ID++;}
     }
     

    scanf里面一大串都是什么?

    图解

    在这里插入图片描述

    还有写这段代码时候必须包含等号,不能只写大于号

    if (ap->ID == BOOK_MAX){printf("通讯录满了,请删除一些联系人再添加!n");}
     

    不然会警告

    在这里插入图片描述

    最后别忘了填写完一个人的信息的时候,记录的ID需要增加


    4. 打印联系人

    既然已经完成了添加联系人,那么我们就不按顺序,看看如何打印我们所有联系人的成员吧

    打印联系人函数

    直接用一个for循环搞定~

    //显示所有联系人
     void print_book(struct address_book* ap)
     {int i = 0;for (i = 0; i < ap->ID; i++){printf("联系人姓名:%sn性别:%sn年龄:%dn电话:%sn邮箱地址:%sn", ap->p[i].name, ap->p[i].gender, ap->p[i].age,ap->p[i].tele,ap->p[i].email);}
     }
     

    搭配添加联系人食用~,结果如下图:

    在这里插入图片描述


    5. 删除联系人

    我们发现,删除/查找/修改 联系人功能中,都会包含有 查找联系人这个动作

    用for循环遍历一遍,查找是否有这个联系人

    //查找联系人
     int find_contact(const struct address_book* ap, const char* name)
     {int i = 0;for (i = 0; i < ap->ID; i++){if (strcmp(ap->p[i].name, name) == 0){return 1;}}return -1;
     }
     

    找到了之后图解:

    在这里插入图片描述

    //删除联系人
     void del_contact(struct address_book* ap)
     {if (ap->ID == 0)//判断通讯录是否为空{printf("无可删除联系人");return;}char name[NAME_MAX] = { 0 };//存放查找的姓名printf("请输入删除的联系人姓名:");scanf("%s", name);int ret = find_contact(ap, name);if (ret == -1){printf("该联系人不存在");}else{//删除联系人int j = 0;for (j = ret; j < ap->ID - 1; j++){ap->p[j] = ap->p[j + 1];}ap->ID--;//少了一个数字printf("删除成功!n");}}
     

    代码运行效果:

    在这里插入图片描述

    在这里插入图片描述

    我的舍友就这样成功被我删除了哈哈哈哈


    6. 查找指定联系人

    这个代码有了上面几个代码的铺垫,直接复制粘贴修改一些变量就可以!

    看看代码是不是有点熟悉,copy就完事了

    //查找指定联系人
     void seek_contact(const struct address_book* ap)//我们只是查找不作修改
     {char name[NAME_MAX];printf("请输入需要查找的联系人姓名:");scanf("%s", &name);int ret = find_contact(ap, name);if (ret == -1){printf("该联系人不存在");}else{printf("找到了!n联系人姓名:%sn性别:%sn年龄:%dn电话:%sn邮箱地址:%snn",ap->p[ret].name,ap->p[ret].gender,ap->p[ret].age,ap->p[ret].tele,ap->p[ret].email);}
     }
     

    运行效果:

    在这里插入图片描述


    7. 修改联系人

    同理,也是copy + 稍微修改一下就完事了

    //修改联系人
     void modify_contact(struct address_book* ap)
     {char name[NAME_MAX];printf("请输入需要查找的联系人姓名:");scanf("%s", &name);int ret = find_contact(ap, name);if (ret == -1){printf("该联系人不存在");}else{printf("开始修改联系人信息!n");printf("请重新输入联系人姓名:");scanf("%s", ap->p[ret].name);printf("请重新输入联系人性别:");scanf("%s", ap->p[ret].gender);printf("请重新输入联系人年龄:");scanf("%d", &(ap->p[ret].age));printf("请重新输入联系人电话:");scanf("%s", ap->p[ret].tele);printf("请重新输入联系人邮箱地址:");scanf("%s", ap->p[ret].email);printf("-----修改完成-----n");}}
     

    运行效果:

    在这里插入图片描述

    在这里插入图片描述


    8. 排序联系人

    我们用qsort快排进行联系人的姓名排序

    int compare(const void* e1, const void* e2)
     {return (strcmp((const char*)e1, (const char*)e2));
     }//排序联系人
     void sort_contact(struct address_book* ap)
     {qsort(ap->p->name, ap->ID, sizeof(ap->p[0]), compare);printf("排序完成,请选择显示所有联系人进行查看!n");}
     

    然后,我将前面的exit改成了大写

    因为出现了问题!!!

    在stdlib.h文件的存在情况下,exit是已经被使用的

    而我再使用,与库函数冲突,会报错!!

    在发现了原因的情况下,修改之后

    效果如下:

    在这里插入图片描述



    标签:

    上一篇: 11个前端工程师必备的网站 下一篇:
    素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。