目录
今天实现同通讯录的功能。在学习了结构体和其他的自定义的类型之后,我们就可以实现一个的通讯录。
实现一个通讯录:
那接下来我们将从test.c 测试代码 contact.h 声明 contact.c 实现 去实现
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"contact.h"
- void menu()
- {
- printf("************************************");
- printf("********1.add 2.del************");
- printf("********3.search 4.modify*********");
- printf("********5.show 6.sort***********");
- printf("********0.exit ***********");
- printf("************************************");
- }
- enum Option
- {
- EXIT,//0
- ADD,//1
- DEL,//2
- SEARCH,//3
- MODIFY,//4
- SHOW,//5
- SORT,//6
- };
- int main()
- {
- int input = 0;
- Contact con;//创建通讯录con
- do
- {
- menu();
- printf("请输入你的选择:>\n");
- scanf("%d", &input);
- switch (input)//这里为了代码更加清晰用枚举常量
- {
- case ADD:
- break;
- case DEL:
- break;
- case SEARCH:
- break;
- case MODIFY:
- break;
- case SHOW:
- break;
- case SORT:
- break;
- case EXIT:
- printf("退出通讯录\n");
- break;
- default:
- printf("选择错误,请重新选择:>\n");
- break;
- }
- } while (input);
- return 0;
- }
Contact con;//创建通讯录con

InitContact(&con);
这里需要特别注意的是,结构体传参到底是传值还是传地址??🆗忘了小朋友戳一戳
AddContact(&con);
ShowContact(&con);//即使这里不需要& 但是出于效率考虑还是需要
DelContact(&con);
SearchContact(&con);
ModifyContact(&con);
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"contact.h"
- void menu()
- {
- printf("************************************\n");
- printf("********1.add 2.del************\n");
- printf("********3.search 4.modify*********\n");
- printf("********5.show 6.sort***********\n");
- printf("********0.exit ***********\n");
- printf("************************************\n");
- }
- enum Option
- {
- EXIT,//0
- ADD,//1
- DEL,//2
- SEARCH,//3
- MODIFY,//4
- SHOW,//5
- SORT,//6
- };
- int main()
- {
- int input = 0;
- //创建通讯录
- Contact con;
- //初始化通讯录
- InitContact(&con);
- do
- {
- menu();
- printf("请输入你的选择:>\n");
- scanf("%d", &input);
- switch (input)//这里为了代码更加清晰用枚举常量
- {
- case ADD:
- AddContact(&con);
- break;
- case DEL:
- DelContact(&con);
- break;
- case SEARCH:
- SearchContact(&con);
- break;
- case MODIFY:
- ModifyContact(&con);
- break;
- case SHOW:
- ShowContact(&con);
- break;
- case SORT:
- //SortContact(&con);
- break;
- case EXIT:
- printf("退出通讯录\n");
- break;
- default:
- printf("选择错误,请重新选择:>\n");
- break;
- }
- } while (input);
- return 0;
- }
contact.h文件主要是头文件的包含
在我们写代码的过程中,会调用库函数,需要包含头文件,和声明函数。
所以我们将所有函数声明和头文件放到我们.h 文件中。
当然,在其他.c文件需要使用时,我们只需要包含 我们创造的 头文件"contact.h" 即可。
- 自己创建的头文件用" " 双引号,库函数的头文件用< >
- #pragma once
- #include
- #include
- #include
我们怎样去设置一个人的全部信息呢?姓名+年龄+性别+电话+住址 都是需要不同类型的变量去设置,所以我们把它们都放到【结构体】里面。
- #define NAME_MAX 20
- #define SEX_MAX 20
- #define TELE_MAX 20
- #define ADDR_MAX 20
-
- typedef struct PeoInfo
- {
- char name[NAME_MAX];
- int age;
- char sex[SEX_MAX];
- char tele[TELE_MAX];
- char addr[ADDR_MAX];
- }PeoInfo;
如果我想存放100个人的信息,那我们怎样去存放100个人的信息呢?用结构体数组(所谓就是存放结构体类型变量的数组)
- #define MAX 100
- typedef struct Contact
- {
- PeoInfo data[MAX];//存放数据
- int sz;//记录当前通讯录中存放的人的信息个数
- }Contact;//通讯录

初步创建完成我们的通讯录,那我们调试发现通讯录里面全是随机值,所以我们需要封装一个函数去初始化个人信息。
void InitContact(Contact* pc);
void AddContact(Contact* pc);
void ShowContact(Contact* pc);
void DelContact(Contact *pc);
void SearchContact(Contact* pc);
void ModifyContact(Contact* pc);
- #pragma once
- #include
- #include
- #include
-
- #define NAME_MAX 20
- #define SEX_MAX 20
- #define TELE_MAX 20
- #define ADDR_MAX 30
- #define MAX 100
-
- typedef struct PeoInfo
- {
- char name[NAME_MAX];
- int age;
- char sex[SEX_MAX];
- char tele[TELE_MAX];
- char addr[ADDR_MAX];
- }PeoInfo;
-
- typedef struct Contact
- {
- PeoInfo data[MAX];//存放数据
- int sz;//记录当前通讯录中存放的人的信息个数
- }Contact;
-
- //初始化通讯录
- void InitContact(Contact* pc);
- //增加个人信息
- void AddContact(Contact* pc);
- //展示个人信息
- void ShowContact(Contact* pc);
- //删除个人信息
- void DelContact(Contact *pc);
- //查找个人信息
- void SearchContact(Contact* pc);
- //修改个人信息
- void ModifyContact(Contact* pc);
- //排序
- //void SortContact(Contact* pc);
- void InitContact(Contact* pc)
- {
- assert(pc);
- pc->sz = 0;
- memset(pc->data, 0, sizeof(pc->data));
- }
完成了我们的通讯录的初始化,感觉要长脑子了。 接下来一步一步实现它的功能。

首先,这幅图想说明: data的下标和sz的数值是对应的
- void AddContact(Contact* pc)
- {
- assert(pc);
- printf("请输入名字\n");
- scanf("%s", pc->data[pc->sz].name);//name是数组名,不用&
- printf("请输入年龄\n");
- scanf("%d", &(pc->data[pc->sz].age));//
- printf("请输入性别\n");
- scanf("%s", pc->data[pc->sz].sex);
- printf("请输入电话\n");
- scanf("%s", pc->data[pc->sz].tele);
- printf("请输入地址\n");
- scanf("%s", pc->data[pc->sz].addr);
- //
- pc->sz++;
- printf("增加成功\n");
- }
我们改动了通讯录之后,我们都需要去观察一下通讯录,这个时候需要封装函数去实现这个功能
- void ShowContact(const Contact* pc)
- {
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无需打印\n");
- return 0;
- }
- int i = 0;
- //名字 年龄 性别 电话 地址
- //-左对齐
- //20是需要20字符的位置来放名字
- printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
- for (i = 0; i < pc->sz; i++)
- {
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
- }
关于查找个人信息函数,我们在删除,查找,修改里面都会用的。
- static int FindByName(const Contact* pc, char name[])
- {
- assert(pc);
- int i = 0;
- for (i = 0; i < pc->sz; i++)
- {
- if (strcmp(pc->data[i].name, name) == 0)//遍历一边看是否有相同的名字
- {
- return i;
- }
- }
- return -1;
- }
删除联系人,我们首先需要找到联系人,我们就去封装一个查找的函数【FindByname】:把通讯录遍历一遍,找到了就返回下标,找不到就返回-1。其实我们发现后面 查找 修改 删除的功能都需要用这个函数。
- void DelContact(Contact* pc)//删除
- {
- char name[NAME_MAX];//
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无法删除\n");
- return;
- }
- printf("输入要删除的名字:>");
- scanf("%s", name);
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要删除的人不存在\n");
- return;
- }
- //存在返回这个人的所在data的下标放入ret
- int i = 0;
-
- for (i = ret; i < pc -> sz - 1; i++)//注意不要数组越界
- {
- pc->data[i] = pc->data[i + 1];
- }
- pc->sz--;
- printf("删除成功\n");
- }

- void SearchContact(Contact* pc)
- {
- char name[NAME_MAX];
- assert(pc);
- //查找
- printf("输入要查找的名字:>");
- scanf("%s", name);
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要查找的人不存在\n");
- return;
- }
- //显示
- printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[ret].name, pc->data[ret].age,
- pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
-
- }//打印的是下标为ret里的元素数据
- void ModifyContact(Contact* pc)
- {
- char name[NAME_MAX];
- assert(pc);
- //查找
- printf("输入要修改的名字:>");
- scanf("%s", name);
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要修改的人不存在\n");
- return;
- }
- //修改
- assert(pc);
- printf("请输入名字\n");
- scanf("%s", pc->data[ret].name);//name是数组名,不用&
- printf("请输入年龄\n");
- scanf("%s", &(pc->data[ret].age));
- printf("请输入性别\n");
- scanf("%s", pc->data[ret].sex);
- printf("请输入电话\n");
- scanf("%s", pc->data[ret].tele);
- printf("请输入地址\n");
- scanf("%s", pc->data[ret].addr);
- printf("修改成功\n");
- }//下标是ret的数组元素内的数据被修改
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"contact.h"
- //初始化
- void InitContact(Contact* pc)
- {
- assert(pc);
- pc->sz = 0;
- memset(pc->data, 0, sizeof(pc->data));
- }
-
- //增加
- void AddContact(Contact* pc)
- {
- assert(pc);
- printf("请输入名字\n");
- scanf("%s", pc->data[pc->sz].name);//name是数组名,不用&
- printf("请输入年龄\n");
- scanf("%d", &(pc->data[pc->sz].age));//
- printf("请输入性别\n");
- scanf("%s", pc->data[pc->sz].sex);
- printf("请输入电话\n");
- scanf("%s", pc->data[pc->sz].tele);
- printf("请输入地址\n");
- scanf("%s", pc->data[pc->sz].addr);
- pc->sz++;
- printf("增加成功\n");
- }
-
-
- //展示
- void ShowContact(const Contact* pc)
- {
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无需打印\n");
- return 0;
- }
- int i = 0;
- //名字 年龄 性别 电话 地址
- //-左对齐
- //20是需要20字符的位置来放名字
- printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
- for (i = 0; i < pc->sz; i++)
- {
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
- }
- }
-
-
- //删除,查找,修改都需要使用
- int FindByName(const Contact* pc, char name[])
- {
- assert(pc);
- int i = 0;
- for (i = 0; i < pc->sz; i++)
- {
- if (strcmp(pc->data[i].name, name) == 0)
- {
- return i;
- }
- }
- return -1;
- }
-
- //删除
- void DelContact(Contact* pc)
- {
- char name[NAME_MAX];
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无法删除\n");
- return;
- }
- printf("输入要删除的名字:>");
- scanf("%s", name);
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要删除的人不存在\n");
- return;
- }
- //存在返回这个人的所在data的下标放入ret
- int i = 0;
-
- for (i = ret; i < pc -> sz - 1; i++)
- {
- pc->data[i] = pc->data[i + 1];
- }
- pc->sz--;
- printf("删除成功\n");
- }
-
-
-
- //查找
- void SearchContact(Contact* pc)
- {
- char name[NAME_MAX];
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无法查找\n");
- return;
- }
- //查找
- printf("输入要查找的名字:>");
- scanf("%s", name);
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要查找的人不存在\n");
- return;
- }
- //返回下标显示这个的信息🆗
- printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
- }
-
-
- //修改
- void ModifyContact(Contact* pc)
- {
- char name[NAME_MAX];
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无法修改\n");
- return;
- }
- //查找
- printf("输入要修改的名字:>");
- scanf("%s", name);
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要修改的人不存在\n");
- return;
- }
- //修改
- assert(pc);
- printf("请输入名字\n");
- scanf("%s", pc->data[ret].name);//name是数组名,不用&
- printf("请输入年龄\n");
- scanf("%d", &(pc->data[ret].age));//
- printf("请输入性别\n");
- scanf("%s", pc->data[ret].sex);
- printf("请输入电话\n");
- scanf("%s", pc->data[ret].tele);
- printf("请输入地址\n");
- scanf("%s", pc->data[ret].addr);
- printf("修改成功\n");
- }

信息太多,空间小了;信息太少,空间大了。怎么解决呢?动态内存管理!录入的个人信息,等程序结束之后,就不在了。因为数据是存放在内存中的,只要程序退出,掉电,都会丢失。怎么解决?文件存储,数据库。
这个等到我们学习完动态内存和文件操作再去讲解。 ✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!希望大家都有好好学习,好好敲代码。好好生活哦。🆗
代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com】
联系------→【邮箱:2784139418@qq.com】