前言:
本期讲解的是如何实现通讯录的增、删、查、改四个功能,此次采用了分文件的方式进行书写,分别分为game.h、test.c和game.c,并且采用了动态开辟的方式进行数据的存储。
game.h
这部分内容主要包含的是通讯录结构体的定义,一些宏定义,比如存储名字的数组空间是多少,一个通讯录最初的存储容量是多少等等,以及一些函数的声明。
test.c
为了方便用户选择所使用的功能,可以设计一个switch的结构来进行实现,并且为了方便用户使用,我们可以在外层再加一个do while的循环,来帮助用户在选择完一个操作后可以继续选择是否进行下一个操作。中间我采用了枚举的方式进行书写,这样可以提高阅读者对代码的可读性。
#include"contact.h"
void menu()
{
printf("************************************\n");
printf("********* 1. Add 2. Del *******\n");
printf("********* 3. search 4.modify *******\n");
printf("********* 5.print 0. exit *******\n");
printf("************************************\n");
}
enum
{
EXIT,
ADD,
DEL,
SREACH,
MODIFY,
PRINT
};
int main()
{
int input = 0;
// 创建通讯录
Contact con;
// 初始化通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
Addcontact(&con);
break;
case DEL:
Delcontact(&con);
break;
case SREACH:
Sreachcontact(&con);
break;
case MODIFY:
Modifycontact(&con);
break;
case PRINT:
print(&con);
break;
case EXIT:
Destorycontact(&con);
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (input);
return 0;
}
game.c的实现
初始化通讯录
首先我们是先要开辟一块存放数据的空间,这里采用malloc进行,函数原型是 void *malloc( size_t size );括号里面是准备开辟多少字节的空间,这样就可以得到我们需要的空间了。perror是一个库函数,它的作用是去在屏幕上打出程序是因为什么原因出错的,而如果pc->date是空指针,说明开辟空间失败,从而perror就会报错。sz是表示目前存放了多少个信息,capacity是表示目前通讯录的最大容量。
void InitContact(Contact* pc)
{
pc->date = (Peoinfo*)malloc(CAPA_MAX * sizeof(Peoinfo));
if (pc->date == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->capacity = CAPA_MAX;
}
增加人员信息
对于增加人员信息,我们只需要依次输入某个人员的各个信息就可以了,再输入完毕时讲sz++,来表明通讯录内的人员增加了一个,但是一直在通讯录进行增加,如果一开始开辟的空间用完了呢?因此在每次增加人员信息之前,我们应该判断一下通讯录是否已经满了,如果满了就进行增容。增容的话我们采用realloc,它的函数原型是void *realloc( void *memblock, size_t size );括号里的参数第一个是原来开辟空间的首地址,第二个是你第二次需要开辟的空间大小,然后我们可以再将我们刚开始定义的capacity容量进行修改就可以了。
void Addcontact(Contact* pc)
{
// 考虑增容
if (pc->sz == pc->capacity)
{
Peoinfo* ptr = (Peoinfo*)realloc(pc->date, (pc->capacity + INC_SZ) * sizeof(Peoinfo));
if (ptr != NULL)
{
pc->date = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
}
else
{
perror("Addcontact");
return;
}
}
printf("请输入姓名:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入年龄:>");
scanf("%d", &pc->date[pc->sz].age);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
打印通讯录
进行依次打印就可以了,不过我们中间可以加上\t来让我们的数据进行分隔开,-10s的意思就是与下一个数据空出10格空间,这里就是姓名和性别中间空了十个格子,大家可以试着去掉这些再加上分别打印一下,体会一下这个效果。
void print(Contact* pc)
{
// 打印标题
printf("%-10s\t%-5s\t%s\t%-12s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-5s\t%d\t%-12s\t%-20s\n", pc->date[i].name,
pc->date[i].sex,
pc->date[i].age,
pc->date[i].tele,
pc->date[i].addr);
}
}
查找人员
查找人的话我们只需要找到这个人的所在的下标就可以了,但是我们可以想一想,当删除某个人之前,我们是不是得先找到这个人,然后才能删除他,所以我们也可以把实现查找人员下标功能写成一个函数,也算是方便多次使用了。
static int Find(Contact* pc,char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void Sreachcontact(Contact* pc)
{
char name[NAME] = {
0 };
printf("请输入需要查找人员的名字:>");
scanf("%s", name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("人员不存在\n");
}
printf("%-10s\t%-5s\t%d\t%-12s\t%-20s\n", pc->date[ret].name,
pc->date[ret].sex,
pc->date[ret].age,
pc->date[ret].tele,
pc->date[ret].addr);
}
删除人员
删除人员就很简单了,我们只需要先找到他的下标,然后将他后面的人员信息一个一个往前覆盖,就可以完成删除了。但是在删除之前我们还需要判断一下通讯录是否为空,如果是空的话那就是没有人员信息,那我们还删除什么呢?请看代码:
void Delcontact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[NAME] = {
0 };
printf("请输入需要删除人员的名字:>");
scanf("%s", name);
// 先找到所需要删除人员的下标
int ret = Find(pc,name);
if (ret == -1)
{
printf("人员不存在\n");
return;
}
// 删除
int i = 0;
for (i = ret; i < pc->sz-1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
修改信息
同样的,在修改时我们先找到这个人信息所在的下标,然后直接重新输入我们想修改的信息就可以了。
void Modifycontact(Contact* pc)
{
char name[NAME] = {
0 };
printf("请输入需要修改人员的名字:>");
scanf("%s", name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("人员不存在\n");
}
printf("请输入姓名:>");
scanf("%s", pc->date[ret].name);
printf("请输入性别:>");
scanf("%s", pc->date[ret].sex);
printf("请输入年龄:>");
scanf("%d", &pc->date[ret].age);
printf("请输入电话:>");
scanf("%s", pc->date[ret].tele);
printf("请输入地址:>");
scanf("%s", pc->date[ret].addr);
printf("修改成功\n");
}
销毁通讯录
因为我们采取的动态开辟的方法来进行的,所以在最后使用完之后需要将申请的空间进行释放,方式造成内存泄漏。
void Destorycontact(Contact* pc)
{
free(pc->date);
pc->date = NULL;
pc->sz = 0;
pc->capacity = 0;
}
在这里为大家奉上全部代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define NAME 10
#define SEX 5
#define TELE 12
#define ADDR 20
#define CAPA_MAX 3
#define INC_SZ 2
//创建通讯录人员信息
typedef struct PeoInfo
{
char name[NAME];
char sex[SEX];
int age;
char tele[TELE];
char addr[ADDR];
}Peoinfo;
typedef struct Contact
{
Peoinfo* date;
int sz;
int capacity;
}Contact;
// 初始化通讯录
void InitContact(Contact* pc);
// 增加人员信息
void Addcontact(Contact* pc);
//打印通讯录信息
void print(Contact* pc);
// 删除信息
void Delcontact(Contact* pc);
// 查找信息
void Sreachcontact(Contact* pc);
// 修改信息
void Modifycontact(Contact* pc);
//销毁通讯录
void Destorycontact(Contact* pc);
#include"contact.h"
void menu()
{
printf("************************************\n");
printf("********* 1. Add 2. Del *******\n");
printf("********* 3. search 4.modify *******\n");
printf("********* 5.print 0. exit *******\n");
printf("************************************\n");
}
enum
{
EXIT,
ADD,
DEL,
SREACH,
MODIFY,
PRINT
};
int main()
{
int input = 0;
// 创建通讯录
Contact con;
// 初始化通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
Addcontact(&con);
break;
case DEL:
Delcontact(&con);
break;
case SREACH:
Sreachcontact(&con);
break;
case MODIFY:
Modifycontact(&con);
break;
case PRINT:
print(&con);
break;
case EXIT:
Destorycontact(&con);
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (input);
return 0;
}
#include"contact.h"
void InitContact(Contact* pc)
{
pc->date = (Peoinfo*)malloc(CAPA_MAX * sizeof(Peoinfo));
if (pc->date == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->capacity = CAPA_MAX;
}
void Addcontact(Contact* pc)
{
// 考虑增容
if (pc->sz == pc->capacity)
{
Peoinfo* ptr = (Peoinfo*)realloc(pc->date, (pc->capacity + INC_SZ) * sizeof(Peoinfo));
if (ptr != NULL)
{
pc->date = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
}
else
{
perror("Addcontact");
return;
}
}
printf("请输入姓名:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入年龄:>");
scanf("%d", &pc->date[pc->sz].age);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
void print(Contact* pc)
{
// 打印标题
printf("%-10s\t%-5s\t%s\t%-12s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-5s\t%d\t%-12s\t%-20s\n", pc->date[i].name,
pc->date[i].sex,
pc->date[i].age,
pc->date[i].tele,
pc->date[i].addr);
}
}
static int Find(Contact* pc,char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void Delcontact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[NAME] = {
0 };
printf("请输入需要删除人员的名字:>");
scanf("%s", name);
// 先找到所需要删除人员的下标
int ret = Find(pc,name);
if (ret == -1)
{
printf("人员不存在\n");
return;
}
// 删除
int i = 0;
for (i = ret; i < pc->sz-1; i++)
{
pc->date[i] = pc->date[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
void Sreachcontact(Contact* pc)
{
char name[NAME] = {
0 };
printf("请输入需要查找人员的名字:>");
scanf("%s", name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("人员不存在\n");
}
printf("%-10s\t%-5s\t%d\t%-12s\t%-20s\n", pc->date[ret].name,
pc->date[ret].sex,
pc->date[ret].age,
pc->date[ret].tele,
pc->date[ret].addr);
}
void Modifycontact(Contact* pc)
{
char name[NAME] = {
0 };
printf("请输入需要修改人员的名字:>");
scanf("%s", name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("人员不存在\n");
}
printf("请输入姓名:>");
scanf("%s", pc->date[ret].name);
printf("请输入性别:>");
scanf("%s", pc->date[ret].sex);
printf("请输入年龄:>");
scanf("%d", &pc->date[ret].age);
printf("请输入电话:>");
scanf("%s", pc->date[ret].tele);
printf("请输入地址:>");
scanf("%s", pc->date[ret].addr);
printf("修改成功\n");
}
void Destorycontact(Contact* pc)
{
free(pc->date);
pc->date = NULL;
pc->sz = 0;
pc->capacity = 0;
}
总结
- 好耶!!又双叒叕完成了一篇文章,希望能对大家有所帮助嗷!!如果觉得小生写的不错(嘴角上扬),可以动动您灵巧的小手点赞+收藏以示鼓励!!谢谢大家啦~~
好耶!!这就滚去正常总结(被打): - 这个通讯录其实还没有完善,在这个基础上我们还可以去添加一些排序,比如按照名字、电话号什么什么的,以及用一些文件方面的知识,将我们每次继续的信息保存下来,这样在我们下一次打开通讯录的时候让上一次保存的信息依然存在,暂时就只能想到这么多力!!如果还有什么问题大家可以在评论区留言喔 ~ 撒悠啦啦