【数据结构】 顺序表的应用——通讯录项目
个人主页:@我要成为c嘎嘎大王
希望这篇小小文章可以让你有所收获!
目录
前言
一、创建结构体类型——联系人数据
二、通讯录的初始化和销毁
三、通讯录的增删查改
3.1 实现通讯录的“增”功能
3.2 实现通讯录的“删”功能
3.2.1 按名字查找通讯录信息
3.2.2 删除联系人
3.3 实现通讯录的“查”功能
3.4 实现通讯录的“改”功能
3.5 实现通讯录的“展示”功能
四、通讯录菜单
五、效果展示
六、总结
前言
本篇文章将介绍一个基于顺序表的项目——通讯录。
通讯录我们都知道,细细一想通讯录不就是一个顺序表吗?在通讯录中以一个联系人为位,存储着若干个联系人的各种信息,我们也可以对通讯录中的联系人信息进行相应的增、删、查、改操作。但是上篇文章的顺序表存的只是整型数据,而在本文,联系人数据可不只是整形数据,如果想把一个联系人的各种信息以一个联系人为单位存储,就需要用到我们之前学到的内置类型——结构体类型。
接下来将详细介绍基于顺序表的通讯录项目搭建的具体过程。
本文将延用上篇文章中实现好的顺序表代码——>【数据结构】顺序表的实现
一、创建结构体类型——联系人数据
我们需要存联系人的姓名、性别、年龄、电话号码、地址等信息,如果把联系人看作一个单位、就需要一个类型能将联系人的这些信息储存,我们很容易的就能想到自定义类型——结构体类型。
所以第一步我们需要创建一个结构体类型来保存联系人的这些信息。
#define NAME_MAX 20#define GENDER_MAX 20#define TEL_MAX 20#define ADDR_MAX 100typedef struct PersonInfo{char name[NAME_MAX];//姓名char gender[GENDER_MAX];//性别int age;//年龄char tel[TEL_MAX];//电话号码char addr[ADDR_MAX];//住址}PeoInfo;
我们将保存名字等信息的数组大小用宏代替,这样方便后续可能的更改。
创建好用于保存联系人信息的结构体类型后,接着就需要将顺序表头文件中的动态顺序表管理的数据类型替换掉,不要忘了包含相应的头文件。
#define _CRT_SECURE_NO_WARNINGS#include#include#include#include#include\"Contect_Seqlist.h\"//typedef int SLDataType; //实现顺序表 类型为inttypedef PeoInfo SLDataType;//实现通讯录 类型为PeoInfo结构体类型// 动态顺序表 -- 按需申请typedef struct SeqList{ SLDataType* arr; int size; // 有效数据个数 int capacity; // 空间容量}SL;
二、通讯录的初始化和销毁
我们操作通讯录,实际上就是操作顺序表(一定要理解这句话,否则会被绕晕)
那么通讯录的初始化和销毁,实际上就是顺序表的初始化和销毁。
为了方便识别,我们在通讯录头文件中给\"struct Seqlist\"重新改个名字就叫\"contact\"。要想使用顺序表头文件中的\"struct Seqlist\"原本是需要在通讯录头文件包含顺序表头文件的,但是顺序表头文件中已经包含了通讯录头文件,而我们知道头文件是不能互相包含的,那为了在通讯录头文件中使用\"struct Seqlist\",需要在使用前进行前置类型声明。
// Contect_Seqlist.h 通讯录头文件//前置声明typedef struct SeqList contact;//初始化通讯录void InitContact(contact* con);//销毁通讯录数据void DestroyContact(contact* con);
//Contect_Seqlist.c//初始化通讯录void InitContact(contact* con) {SLInit(con);}//销毁通讯录数据void DestroyContact(contact* con) {SLDestroy(con);}
三、通讯录的增删查改
3.1 实现通讯录的“增”功能
在通讯录中添加联系人实际上就是上篇文章中的在顺序表中插入一个整型数据,只不过在这里把一个联系人当作一个单位。
首先我们需要一个结构体变量来存联系人的各种信息,然后再将这个结构体变量插入到通讯录(顺序表)中,插入方式可以有多种,本文选择尾插。
//Contect_Seqlist.h//添加通讯录数据void AddContact(contact* con);
//Contect_Seqlist.c//添加通讯录数据void AddContact(contact* con) {PeoInfo peoinfo; //输入联系人的信息printf(\"请输入联系人的姓名:\");scanf(\"%s\", peoinfo.name);printf(\"请输入联系人的性别:\");scanf(\"%s\", peoinfo.gender);printf(\"请输入联系人的年龄:\");scanf(\"%d\", &peoinfo.age);printf(\"请输入联系人的电话号码:\");scanf(\"%s\", peoinfo.tel);printf(\"请输入联系人的住址:\");scanf(\"%s\", peoinfo.addr); //插入到通讯录(顺序表)中SLPushBack(con, peoinfo); printf(\"添加成功\\n\");}
3.2 实现通讯录的“删”功能
删除联系人操作有个大前提,就是要删除的这个联系人必须存在,否则无法删除。
怎么判断要删除的这个联系人是否存在呢?
首先我们需要获取要删除的这个联系人的信息,然后在通讯录中查找,如果找到了就可以执行删除操作,如果没找到就不能进行删除操作。
3.2.1 按名字查找通讯录信息
//Contect_Seqlist.h//按名字查找通讯录信息int FindByname(contact* con, char* dest);
//Contect_Seqlist.c//按名字查找通讯录信息int FindByname(contact* con, char* dest) {for (int i = 0; i size; i++) {if (strcmp(con->arr[i].name, dest) == 0) {return i;}}return -1;}
上面我们是通过联系人的姓名来判断是否存在这个联系人,姓名是字符串,比较字符串需要用到字符串比较函数 strcmp,使用这个函数需要包含头文件
如果找到匹配的姓名,则返回这个姓名对应联系人对应的下标,若没找到匹配的姓名,则返回无效下标 ‘ -1 ’
3.2.2 删除联系人
我们通过“FindByname”函数返回值找到我们要删除的联系人信息后,进行删除操作,本文使用顺序表中的“Erase”函数实现删除操作
//Contest_Seqlist.h//删除通讯录数据void DelContact(contact* con);
//Contect_Seqlist.c//删除通讯录数据void DelContact(contact* con) {PeoInfo peoinfo;printf(\"请输入要删除的联系人的姓名:\");scanf(\"%s\", peoinfo.name);int find = FindByname(con, peoinfo.name);if (find != -1) {SLErase(con, find);printf(\"删除成功\");}else printf(\"未查找到该联系人\\n\");}
3.3 实现通讯录的“查”功能
我们可以延用之前写好的根据联系人姓名来查找“
FindByname”
函数。
//Contect_Seqlist.h//查找通讯录数据void FindContact(contact* con);
//Contect_Seqlist.c//查找通讯录数据void FindContact(contact* con) {PeoInfo peoinfo;printf(\"请输入要查找的联系人的姓名:\");scanf(\"%s\", peoinfo.name);int find = FindByname(con, peoinfo.name);if (find != -1) {printf(\"%2s %8s %8s %8s %8s\\n\", \"姓名\", \"性别\", \"年龄\", \"电话\", \"地址\");printf(\"——— ——— ——— ——— ———\\n\");printf(\"%2s %7s %7d %9s %9s\\n\",con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);}else printf(\"未查找到该联系人\\n\");}
3.4 实现通讯录的“改”功能
修改联系人信息也有个大前提,就是要修改的这个联系人必须存在,才能被修改。所以我们通过“FindByname”函数返回值找到我们要修改的联系人信息后,进行修改操作
//Contect_Seqlist.h//修改通讯录数据void ModifyContact(contact* con);
//Contect_Seqlist.c//修改通讯录数据void ModifyContact(contact* con) {PeoInfo peoinfo;printf(\"请输入要修改的联系人的姓名:\");scanf(\"%s\", peoinfo.name);int find = FindByname(con, peoinfo.name);if (find != -1) {printf(\"请输入修改后的联系人的姓名:\");scanf(\"%s\", con->arr[find].name);printf(\"请输入修改后的联系人的性别:\");scanf(\"%s\", con->arr[find].gender);printf(\"请输入修改后的联系人的年龄:\");scanf(\"%d\", &con->arr[find].age);printf(\"请输入修改后的联系人的电话号码:\");scanf(\"%s\", con->arr[find].tel);printf(\"请输入修改后的联系人的住址:\");scanf(\"%s\", con->arr[find].addr);}else printf(\"未查找到该联系人\\n\");}
3.5 实现通讯录的“展示”功能
我们平时使用的通讯录是可以展示联系人的各种信息的,这里我们也简单地实现一下,将所有联系人的信息打印出来供使用者看。
//Contect_Seqlist.h//展示通讯录数据void ShowContact(contact* con);
//Contect_Seqlist.c//展示通讯录数据void ShowContact(contact* con) {printf(\"%2s %8s %8s %8s %8s\\n\", \"姓名\", \"性别\", \"年龄\", \"电话\", \"地址\");printf(\"——— ——— ——— ——— ———\\n\");for (int i = 0; i size; i++) {printf(\"%2s %7s %7d %9s %9s\\n\",con->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}}
四、通讯录菜单
在实现完通讯录的相关操作后,我们接着制作一个简易菜单。
//Contect_Test_Seqlist.c#include\"Seqlist.h\"void menu(){printf(\"************* 通讯录 *************\\n\");printf(\"**** 1.添加联系人 2.删除联系人 ****\\n\");printf(\"**** 3.修改联系人 4.查找联系人 ****\\n\");printf(\"**** 5.展示通讯录 0.退出通讯录 ****\\n\");printf(\"************************************\\n\");}int main() {contact con;InitContact(&con);int input = 0;do {menu();printf(\"请输入要进行的操作:\");scanf(\"%d\", &input);switch (input) {case 1:AddContact(&con);break;case 2:DelContact(&con);break;case 3:ModifyContact(&con);break;case 4:FindContact(&con);break;case 5:ShowContact(&con);break;case 0:printf(\"正在退出通讯录......\");break;default:printf(\"选择错误,请重新选择\");break;}} while (input != 0); //销毁通讯录DestroyContact(&con);return 0;}
五、效果展示
六、总结
- 通讯录其实就是顺序表,只是上文的顺序表存储的是整型数据,而本文的顺序表存储的结构体类型数据而已
- 在本篇文章中我们更多的是对保存联系人信息的结构体类型进行相应的操作,通讯录实际上就是顺序表,而顺序表的相关操作是我们已经实现好了的,所以我们只需要拿来用就可以了
- 通讯录就像是在顺序表的外面又包装了一层其他的操作,使其完成对联系人信息的增删查改操作
完
若上述文章有什么错误,欢迎各位大佬及时指出,我们共同进步!