在学习完结构体的知识后,我们就可以开始尝试实现通讯录了。首先,通讯录的基本功能大致有以下几个:联系人信息 的添加、删除、修改、查找、显示。而联系人的信息包括了姓名、性别、年龄、住址、电话号码五个方面的信息。
注:作者使用的编译器为vs2019
目录
1.整体的思路
1.1.模块化编程
为了控制程序设计的复杂性,我们可以将通讯录的实现拆分为三个文件,定义contact.h 用于存放函数声明与在后续需要使用到的头文件,后续函数的声明基本都将放到contact.h中!contact.c用于实现contact头文件中函数的定义;test.c用于定下实现程序的整体逻辑框架并在编写过程中对contact.c中的函数进行测试。
1.2.程序框架建立
程序的整个逻辑框架我们在test.c中建立,首先为了向使用者说明我们的通讯录的使用方法,我们需要定义一个打印菜单的函数menu
void menu()
{
printf("*********************************************\n");
printf("********** 1.add 2.del *********\n");
printf("********** 3.search 4.modify *********\n");
printf("********** 5.show 0.exit *********\n");
printf("*********************************************\n");
}
在主函数中,通过switch语句,使用者可以选择想要使用的功能,同时,为了方便使用者多次使用通讯录,我们可以把实现流程放入do-while循环中,先用伪代码测试框架可行性,具体功能在后续编写的函数中实现,代码如下:
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("添加联系人信息\n");
break;
case 2:
printf("删除联系人信息\n");
break;
case 3:
printf("查找联系人信息\n");
break;
case 4:
printf("修改联系人信息\n");
break;
case 5:
printf("显示联系人信息\n");
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("请重新选择\n");
break;
}
} while (input != 0);
return 0;
}
通过运行可以看到,我们主函数的逻辑无误。
1.3.通讯录的定义及初始化
在开头我们提到了联系人的信息包含了姓名、性别、年龄、住址、电话号码这些信息,可以发现,用结构体来处理这些信息是非常方便的,所以接下来我们在contact.h中通过结构体来实现通讯录的定义。将储存这些个人信息的结构体命名为peoinfor(people information), 而作为通讯录,需要储存多个联系人的信息,因此需要一个结构体数组来储存,同时,为了完成删除、查找、修改的功能,我们需要记录数组中已经存入了多少变量,为此我们可以再定义一个结构体Contact,成员为peoinfor类型的数组data与用于记数的int类型变量sz。代码如下:
#define MAX 100
#define NAME_MAX 10
#define SEX_MAX 5
#define ADDR_MAX 20
#define TEL_MAX 12
typedef struct peoinfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char addr[ADDR_MAX];
char tel[TEL_MAX];
}peoinfo;
typedef struct Contact
{
peoinfo data[MAX];
int sz;
}Contact;
(typedef在这里是用来把结构体变量声明得更加简洁的,为了方便后续对函数参数的修改,我们在contact.h头文件中用宏定义了一些参数)
接下来我们在test.c中定义Contact类型的变量con,并封装一个函数对其进行初始化
contact.h中:
void initcontact(Contact* pc);
contact.c中:
void initcontact(Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
(memset函数的头文件为#include<string.h>)
在定义完储存通讯录信息的结构体变量后,我们就可以开始将通讯录的功能分别用函数来完成了!
首先在contact.h中对函数进行声明:
void initcontact(Contact* pc);
void addcontact(Contact *pc);
void delcontact(Contact *pc);
void searchcontact(Contact *pc);
void modifycontact(Contact *pc);
void showcontact(Contact *pc);
int main()
{
int input = 0;
Contact con;
initcontact(&con);
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
addcontact(&con);
break;
case 2:
delcontact(&con);
break;
case 3:
searchcontact(&con);
break;
case 4:
modifycontact(&con);
break;
case 5:
showcontact(&con);
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("请重新选择\n");
break;
}
} while (input != 0);
return 0;
}
接下来我们将在contact.c中完成各个函数的定义
2.通讯录功能的实现
2.1.添加联系人信息
通讯录存在容量大小,在这里我们定义它的容量为100,那么存入联系人信息超过100时,程序将提醒用户无法再添加,之后按照给结构体成员赋值的方法分别把各种信息输入即可,同时每次输入完成后,计数器加一,记录当前存入的联系人信息条数
void addcontact(Contact* pc)
{
if (pc->sz == MAX)
{
printf("通讯录已满,无法读入\n");
}
printf("请输入姓名:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别: ");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄: ");
scanf("%d", &pc->data[pc->sz].age);
printf("请输入住址: ");
scanf("%s", &pc->data[pc->sz].addr);
printf("请输入电话: ");
scanf("%s", &pc->data[pc->sz].tel);
pc->sz++;
}
2.2.显示联系人信息
在存入联系人信息后,为了更方便地测试代码是否正确无误,我们可以先实现showcontact函数,
这里为了让信息的显示更加美观整齐,打印时可以对打印格式稍作修改
void showcontact(Contact* pc)
{
int i = 0;
printf("%-10s %-10s %-10s %-10s %-10s\n", "姓名", "年龄", "性别", "地址", "电话");
for (i = 0;i < pc->sz;i++)
{
printf("%-10s %-10d %-10s %-10s %-10s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].addr,
pc->data[i].tel);
}
/*printf("%d\n", pc->sz);*/
}
2.3.删除联系人信息
在实现delcontact函数功能之前,我们发现无论是信息的删除还是修改或是查找,都需要知道变量的位置,那么我们可以将通过联系人姓名查找联系人这个功能封装为一个函数。
int Find_by_name(Contact* pc, char name[10])
{
int ret = 0;
for (int i = 0;i < pc->sz;i++)
{
ret = strcmp(name, pc->data[i].name);
if (ret == 0) return i;
}
return -1;
}
(因为strcmp函数在两个字符串相等时将返回0,所以当ret为0时,说明找到了要找到联系人,返回值i就是要找的数组下标了)
由于删除某个特定联系人后,该联系人信息消失,同时计数器sz减一,故我们可以在该联系人处开始for循环遍历,让后一位元素覆盖前一位元素来实现删除过程
void delcontact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
printf("请输入要删除联系人的姓名:");
char name[10];
scanf("%s", name);
int ret = Find_by_name(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
if (ret != -1)
{
for (int i = ret;i < pc->sz-1;i++)
{
pc->data[i] = pc->data[i + 1];
}
}
pc->sz--;
printf("删除成功\n");
}
2.4.查找联系人信息
由于我们已经通过Find_by_name函数实现了查找联系人,只需要打印该联系人的信息即可
void searchcontact(Contact* pc)
{
int ret = 0;
printf("请输入要查找联系人的名字:");
char name[10];
scanf("%s", &name);
ret=Find_by_name(pc, name);
if (ret == -1)
{
printf("查找的联系人不存在\n");
return;
}
if(ret!=-1)
printf("%-10s %-10d %-10s %-10s %-10s\n", pc->data[ret].name,
pc->data[ret].age,
pc->data[ret].sex,
pc->data[ret].addr,
pc->data[ret].tel);
}
2.5.修改联系人信息
在查找到要修改联系人后,对其中的信息分别进行修改,修改方式与添加信息类似
void modifycontact(Contact* pc)
{
char name[10];
printf("请输入要修改联系人的名字:");
scanf("%s", name);
int ret = 0;
ret = Find_by_name(pc, name);
if (ret == -1)
printf("要修改的联系人不存在\n");
printf("请输入姓名: ");
scanf("%s", pc->data[ret].name);
printf("请输入性别: ");
scanf("%s", pc->data[ret].sex);
printf("请输入年龄: ");
scanf("%d", &pc->data[ret].age);
printf("请输入住址: ");
scanf("%s", &pc->data[ret].addr);
printf("请输入电话: ");
scanf("%s", &pc->data[ret].tel);
printf("修改完成\n");
}
2.6.通讯录的功能展示
添加:
显示:
删除:
修改:
查找:
3.写在最后
3.1.源码
contact.h部分
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#define MAX 100
#define NAME_MAX 10
#define SEX_MAX 5
#define ADDR_MAX 20
#define TEL_MAX 12
typedef struct peoinfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char addr[ADDR_MAX];
char tel[TEL_MAX];
}peoinfo;
typedef struct Contact
{
peoinfo data[MAX];
int sz;
}Contact;
void initcontact(Contact* pc);
void addcontact(Contact *pc);
void delcontact(Contact *pc);
void searchcontact(Contact *pc);
void modifycontact(Contact *pc);
void showcontact(Contact *pc);
contact.c部分
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"contact.h"
void initcontact(Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
void addcontact(Contact* pc)
{
if (pc->sz == MAX)
{
printf("通讯录已满,无法读入\n");
}
printf("请输入姓名:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别: ");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄: ");
scanf("%d", &pc->data[pc->sz].age);
printf("请输入住址: ");
scanf("%s", &pc->data[pc->sz].addr);
printf("请输入电话: ");
scanf("%s", &pc->data[pc->sz].tel);
pc->sz++;
}
int Find_by_name(Contact* pc, char name[10])
{
int ret = 0;
for (int i = 0;i < pc->sz;i++)
{
ret = strcmp(name, pc->data[i].name);
if (ret == 0) return i;
}
return -1;
}
void delcontact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
printf("请输入要删除联系人的姓名:");
char name[10];
scanf("%s", name);
int ret = Find_by_name(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
if (ret != -1)
{
for (int i = ret;i < pc->sz-1;i++)
{
pc->data[i] = pc->data[i + 1];
}
}
pc->sz--;
printf("删除成功\n");
}
void searchcontact(Contact* pc)
{
int ret = 0;
printf("请输入要查找联系人的名字:");
char name[10];
scanf("%s", &name);
ret=Find_by_name(pc, name);
if (ret == -1)
{
printf("查找的联系人不存在\n");
return;
}
if(ret!=-1)
printf("%-10s %-10d %-10s %-10s %-10s\n", pc->data[ret].name,
pc->data[ret].age,
pc->data[ret].sex,
pc->data[ret].addr,
pc->data[ret].tel);
}
void modifycontact(Contact* pc)
{
char name[10];
printf("请输入要修改联系人的名字:");
scanf("%s", name);
int ret = 0;
ret = Find_by_name(pc, name);
if (ret == -1)
printf("要修改的联系人不存在\n");
printf("请输入姓名: ");
scanf("%s", pc->data[ret].name);
printf("请输入性别: ");
scanf("%s", pc->data[ret].sex);
printf("请输入年龄: ");
scanf("%d", &pc->data[ret].age);
printf("请输入住址: ");
scanf("%s", &pc->data[ret].addr);
printf("请输入电话: ");
scanf("%s", &pc->data[ret].tel);
printf("修改完成\n");
}
void showcontact(Contact* pc)
{
int i = 0;
printf("%-10s %-10s %-10s %-10s %-10s\n", "姓名", "年龄", "性别", "地址", "电话");
for (i = 0;i < pc->sz;i++)
{
printf("%-10s %-10d %-10s %-10s %-10s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].addr,
pc->data[i].tel);
}
/*printf("%d\n", pc->sz);*/
}
test.c部分
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"contact.h"
void menu()
{
printf("*********************************************\n");
printf("********** 1.add 2.del *********\n");
printf("********** 3.search 4.modify *********\n");
printf("********** 5.show 0.exit *********\n");
printf("*********************************************\n");
}
int main()
{
int input = 0;
Contact con;
initcontact(&con);
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
addcontact(&con);
break;
case 2:
delcontact(&con);
break;
case 3:
searchcontact(&con);
break;
case 4:
modifycontact(&con);
break;
case 5:
showcontact(&con);
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("请重新选择\n");
break;
}
} while (input != 0);
return 0;
}
3.2.作者想说的话
作为一枚刚开始学C语言且刚开始写博客的小白,深知自己做得不够好,如果有写得不对的地方欢迎指出,希望在接下来的一年能够不断精进自己,和大家一起进步,祝大家都前程似锦!