🌇个人主页:_麦麦_
📚今日名言:只有走在路上,才能摆脱局限,摆脱执着,让所有的选择,探寻,猜测,想象都生机勃勃。——余秋雨《文化苦旅》
目录
一、前言
二、正文
1.大体框架
2.界面显示
3. 创建通讯录
4.初始化通讯录
5.增加联系人
6.显示联系人
7. 删除联系人
8.查找联系人
9.修改联系人
10. 排序联系人
三、结语
一、前言
在上一章的结构体的学习中,相信小伙伴们或多或少都有所收获,但是有的小伙伴可能会问,结构体到底能用来做什么呢?今天,我们就借助结构体和之前所学的知识来实现通讯录。
二、正文
1.大体框架
相信在座的小伙伴们一定有人做过类似的小游戏或项目,编程的大忌就是将所有的代码都放在同一个文件里,写的时候有多好爽快,后期对代码进行修改和维护的时候就有痛苦。这期通讯录的实现我们大致分为三个模块,一个用于测试通讯录,即对各种函数的调用【text.c】;另一个用于通讯录的实现,其中放置着通讯录功能的具体实现【contact.c】;最后一个就是函数的声明了[contact.h].
2.界面显示
就像之前的扫雷与三子棋游戏一样,这个通讯录的第一步一定是要让使用者看到通讯录的页面,继而在使用者选择之后进行下一步的操作。因而我们仍旧采取do while 循环,先将页面显示,再根据使用者的输入进行相应的操作。具体实现代码如下:
//通讯录界面显示
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");
}
int main()
{
int input = 0;
do
{
menu(); //打印菜单
printf("请选择你所需的功能:");
scanf("%d", &input);
switch (input)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
}
}
while (input);
return 0;
}
在以上代码的逻辑下,使用者刚开始就能够看到我们设置好的界面,并进行功能的输入,如果输入为0就退出通讯录,通讯录为功能相应的数字就进行相应的功能【还未填写完整】,若为其他数字,则重新输入。
3. 创建通讯录
为了实现我们菜单中的各个功能,首先我们要有这些功能的受体——通讯录,只有创建好通讯录 ,才能进行功能的操作。在生活中,我们手机上的通讯录都存有联系人的相关信息,例如姓名,年龄,性别,手机号码等等 ,其次在后面的功能中我们还需要知道这个通讯录中联系人的数量是多少。显然,我们需要一个自定义结构变量来定义通讯录,在这个结构体中有两个变量,一个是存放联系人信息的变量,另一个是存放联系人数量的变量。而存放联系人的信息显然需要一个数组,数组的大小即对应着能存放多少联系人,而数组中的元素就是联系人的信息,这也无法用一个单一类型变量来定义,所以我们还需要额外定义一个结构体变量来代表联系人的各种信息。具体代码如下:
//结构体——联系人的信息
struct peo
{
char name[20]; //姓名
char sex[10]; //性别
int age; //年龄
char addr[40]; //地址
char tel[20]; //电话
};
//结构体——通讯录
typedef struct contact
{
struct peo Peo[contact_num]; //通讯录中联系人的信息
int sz; //当前存放联系人的个数
}contact;
4.初始化通讯录
在通讯录的创建之后,就是对其的初始化了,为了方便,我们就都置成0就好了。
//Init_Contact——初始化通讯录
void Init_Contact(contact* pc)
{
pc->sz = 0;
memset(pc, 0, sizeof(pc->Peo));
}
5.增加联系人
在通讯录的创建和初始化完成之后,就是通讯录功能的实现了。首先是“增加联系人”这一功能。我们先是定义一个函数,这个函数的参数就是我们的通讯录,采用传递通讯录地址的方式,返回值为空,因为我们只是对通讯录的内容进行改变,并不需要返回任何东西。然后是函数的具体实现,我们要做的是在联系人信息这一数组中添加一个联系人,并在添加之后将通讯录当前存储的联系人数量+1。此外如果通讯录已满,我们需要提醒使用者无法再添加联系人。具体代码如下:
//Add——增加联系人
void Add(contact* Contact)
{
assert(Contact);
if (Contact->sz < contact_num)
{
printf("请输入联系人的姓名:>\n");
scanf("%s", (Contact->Peo[Contact->sz]).name);
printf("请输入联系人的性别:>\n");
scanf("%s", Contact->Peo[Contact->sz].sex);
printf("请输入联系人的年龄:>\n");
scanf("%d", &(Contact->Peo[Contact->sz].age));
printf("请输入联系人的地址:>\n");
scanf("%s", Contact->Peo[Contact->sz].addr);
printf("请输入联系人的电话:>\n");
scanf("%s", Contact->Peo[Contact->sz].tel);
Contact->sz++;
}
else
printf("通讯录已满无法添加\n");
}
6.显示联系人
为了观察我们在执行增加联系人这个函数是否成功,我们接下来进行“显示联系人”这一功能的实现。同样的先是定义显示联系人这一函数,函数参数是通讯录,采取传址调用的方式,无需返回任何参数。函数的实现就是依据通讯录中所存储的联系人数量,来调用存储联系人信息的数组,并将其显示在屏幕上,为了数据显示的整齐和美观,笔者对打印的数据类型进行了小小的改善,对数据所占空间进行了设置,并将数据左对齐并在数据后输出一个水平制表符。
//Show——展示联系人
void Show( const contact* Contact)
{
assert(Contact);
int pos = 0; //联系人对应下标
printf("%-20s\t%-10s\t%-4s\t%-40s\t%-20s\n","姓名", "性别", "年龄", "地址", "电话");
for (pos = 0; pos < Contact->sz; pos++)
{
printf("%-20s\t%-10s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,
Contact->Peo[pos].sex,
Contact->Peo[pos].age,
Contact->Peo[pos].addr,
Contact->Peo[pos].tel);
}
}
7. 删除联系人
首先是“删除联系人”这一函数的定义,参数为通讯录这一结构体,采取传址调用的方式,返回参数无。继而是函数具体的实现,笔者是根据使用者所输入的所要删除联系人的姓名来找到联系人在数组中对应的下标,从而进行各项信息的删除。这里有个小技巧,无论是删除联系人,修改联系人,搜索联系人都需要在根据输入的姓名对联系人进行查找,因而我们可以将这个功能封装成一个函数,在使用这一功能的时候只需要调用就行了。具体代码实现如下:
//Find_by_name——通过姓名,找到联系人所对应的下标
int Find_by_name( const contact* Contact, char *name)
{
int i = 0;
for (i = 0; i < Contact->sz; i++)
{
if (strcmp(&(Contact->Peo[i].name),name)==0)
return i;
}
return -1;
}
//Del——删除联系人
void Del(contact* Contact)
{
char name[20] = { 0 };
int i = 0;
printf("请输入要删除的联系人:>");
scanf("%s", name);
int pos = Find_by_name(Contact, &name);
if (-1 == pos)
{
printf("该联系人不存在\n");
return;
}
else
{
for (i = pos; i < Contact->sz-1; i++)
{
Contact->Peo[i] = Contact->Peo[i + 1];
}
Contact->sz--;
}
}
8.查找联系人
首先是对“查找联系人”函数的定义,函数参数为通讯录,采取传址调用的方式,返回参数为0。然后是具体功能的实现,先是根据输入的姓名查找到对应的下标,再将其显示在屏幕上。具体代码如下:
//Search——搜索联系人
void Search(const contact* Contact)
{
char name[20] = {0};
printf("请输入要寻找的联系人:>");
scanf("%s", name);
int pos= Find_by_name(Contact, &name);
if (-1==pos)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("%-10s\t%-6s\t%-4s\t%-40s\t%-20s\n", "姓名", "性别", "年龄", "地址", "电话");
printf("%-10s\t%-6s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,
Contact->Peo[pos].sex,
Contact->Peo[pos].age,
Contact->Peo[pos].addr,
Contact->Peo[pos].tel);
}
}
9.修改联系人
首先是对“修改联系人”函数的定义,函数参数为通讯录,采取传址调用的方式,返回参数为0。然后是具体功能的实现,先是根据输入的姓名查找到对应的下标,再依据添加联系人的代码实现联系人信息的修改。具体代码如下:
//Modify——修改联系人
void Modify(contact* Contact)
{
assert(Contact);
char name[20] = { 0 };
printf("请输入要修改的联系人\n");
scanf("%s", name);
int pos = Find_by_name(Contact, &name);
if (-1 == pos)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("请输入联系人的姓名:>\n");
scanf("%s", (Contact->Peo[pos]).name);
printf("请输入联系人的性别:>\n");
scanf("%s", Contact->Peo[pos].sex);
printf("请输入联系人的年龄:>\n");
scanf("%d", &(Contact->Peo[pos].age));
printf("请输入联系人的地址:>\n");
scanf("%s", Contact->Peo[pos].addr);
printf("请输入联系人的电话:>\n");
scanf("%s", Contact->Peo[pos].tel);
}
}
10. 排序联系人
对联系人排序依据有很多,这里仅对联系人的年龄进行排序。采取冒泡排序的方式,冒泡排序的实现在前面的推文已经介绍过了,有兴趣的小伙伴可以康一康。https://blog.csdn.net/m0_73953114/article/details/128766018
//sort——按照年龄对联系人进行排序
void sort(contact* Contact,contact* tmp)
{
//执行冒泡排序的趟数
int i = 0;
for (i = 0; i < Contact->sz - 1; i++)
{
//一趟冒泡排序中交换的次数
int j = 0;
for (j = 0; j < Contact->sz - 1-i; j++)
{
if (Contact->Peo[j].age > Contact->Peo[j + 1].age)
{
tmp->Peo[0] = Contact->Peo[j];
Contact->Peo[j] = Contact->Peo[j + 1];
Contact->Peo[j + 1] = tmp->Peo[0];
}
}
}
}
到这里,整个通讯录就写完了,整体的代码如下:
//main.c
#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");
}
int main()
{
contact Contact; //创建通讯录
contact tmp;
Init_Contact(&Contact); //初始化通讯录
Init_Contact(&tmp);
int input = 0;
do
{
menu(); //打印菜单
printf("请选择你所需的功能:");
scanf("%d", &input);
switch (input)
{
case 1:
Add(&Contact);
break;
case 2:
Del(&Contact);
break;
case 3:
Search(&Contact);
break;
case 4:
Modify(&Contact);
break;
case 5:
Show(&Contact);
break;
case 6:
sort(&Contact,&tmp);
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
}
}
while (input);
return 0;
}
//contact.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#define contact_num 100
#include <stdio.h>
#include <string.h>
#include <assert.h>
//结构体——联系人的信息
struct peo
{
char name[20]; //姓名
char sex[10]; //性别
int age; //年龄
char addr[40]; //地址
char tel[20]; //电话
};
//结构体——通讯录
typedef struct contact
{
struct peo Peo[contact_num]; //通讯录中联系人的信息
int sz; //当前存放联系人的个数
}contact;
void Init_Contact(contact* pc); //初始化通讯录
void Add(contact* Contact); //添加联系人
void Show(const contact* Contact); //展示联系人
void Search(const contact* Contact); //搜索联系人
void Del(contact* Contact); //删除联系人
void Modify(contact* Contact); //修改联系人
void sort(contact* Contact,contact* tmp); //排序联系人——年龄
//contact.c
#include "contact.h"
//Init_Contact——初始化通讯录
void Init_Contact(contact* pc)
{
pc->sz = 0;
memset(pc, 0, sizeof(pc->Peo));
}
//Add——增加联系人
void Add(contact* Contact)
{
assert(Contact);
if (Contact->sz < contact_num)
{
printf("请输入联系人的姓名:>\n");
scanf("%s", (Contact->Peo[Contact->sz]).name);
printf("请输入联系人的性别:>\n");
scanf("%s", Contact->Peo[Contact->sz].sex);
printf("请输入联系人的年龄:>\n");
scanf("%d", &(Contact->Peo[Contact->sz].age));
printf("请输入联系人的地址:>\n");
scanf("%s", Contact->Peo[Contact->sz].addr);
printf("请输入联系人的电话:>\n");
scanf("%s", Contact->Peo[Contact->sz].tel);
Contact->sz++;
}
else
printf("通讯录已满无法添加\n");
}
//Show——展示联系人
void Show( const contact* Contact)
{
assert(Contact);
int pos = 0;
printf("%-10s\t%-6s\t%-4s\t%-40s\t%-20s\n","姓名", "性别", "年龄", "地址", "电话");
for (pos = 0; pos < Contact->sz; pos++)
{
printf("%-10s\t%-6s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,
Contact->Peo[pos].sex,
Contact->Peo[pos].age,
Contact->Peo[pos].addr,
Contact->Peo[pos].tel);
}
}
//Find_by_name——通过姓名,找到联系人所对应的下标
int Find_by_name( const contact* Contact, char *name)
{
int i = 0;
for (i = 0; i < Contact->sz; i++)
{
if (strcmp(&(Contact->Peo[i].name),name)==0)
return i;
}
return -1;
}
//Search——搜索联系人
void Search(const contact* Contact)
{
char name[20] = {0};
printf("请输入要寻找的联系人:>");
scanf("%s", name);
int pos= Find_by_name(Contact, &name);
if (-1==pos)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("%-10s\t%-6s\t%-4s\t%-40s\t%-20s\n", "姓名", "性别", "年龄", "地址", "电话");
printf("%-10s\t%-6s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,
Contact->Peo[pos].sex,
Contact->Peo[pos].age,
Contact->Peo[pos].addr,
Contact->Peo[pos].tel);
}
}
//Del——删除联系人
void Del(contact* Contact)
{
char name[20] = { 0 };
int i = 0;
printf("请输入要删除的联系人:>");
scanf("%s", name);
int pos = Find_by_name(Contact, &name);
if (-1 == pos)
{
printf("该联系人不存在\n");
return;
}
else
{
for (i = pos; i < Contact->sz-1; i++)
{
Contact->Peo[i] = Contact->Peo[i + 1];
}
Contact->sz--;
}
}
//Modify——修改联系人
void Modify(contact* Contact)
{
assert(Contact);
char name[20] = { 0 };
printf("请输入要修改的联系人\n");
scanf("%s", name);
int pos = Find_by_name(Contact, &name);
if (-1 == pos)
{
printf("该联系人不存在\n");
return;
}
else
{
printf("请输入联系人的姓名:>\n");
scanf("%s", (Contact->Peo[pos]).name);
printf("请输入联系人的性别:>\n");
scanf("%s", Contact->Peo[pos].sex);
printf("请输入联系人的年龄:>\n");
scanf("%d", &(Contact->Peo[pos].age));
printf("请输入联系人的地址:>\n");
scanf("%s", Contact->Peo[pos].addr);
printf("请输入联系人的电话:>\n");
scanf("%s", Contact->Peo[pos].tel);
}
}
//sort——按照年龄对联系人进行排序
void sort(contact* Contact,contact* tmp)
{
//执行冒泡排序的趟数
int i = 0;
for (i = 0; i < Contact->sz - 1; i++)
{
//一趟冒泡排序中交换的次数
int j = 0;
for (j = 0; j < Contact->sz - 1-i; j++)
{
if (Contact->Peo[j].age > Contact->Peo[j + 1].age)
{
tmp->Peo[0] = Contact->Peo[j];
Contact->Peo[j] = Contact->Peo[j + 1];
Contact->Peo[j + 1] = tmp->Peo[0];
}
}
}
}
三、结语
关于通讯录的讲解就已经全部结束了,下期我们会分享自定义类型的其他成员!
关注我 _麦麦_分享更多干货:_麦麦_的博客_CSDN博客-领域博主
大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下期见!