前言
在实现通讯录前,我们需先考虑这个通讯录应该具备哪些功能,以下是我写的通讯录功能预览。
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 排序通讯录联系人
代码实现
写通讯录时,我们需要创建三个文件,方便代码的调试和修改。
- test.c 测试整个通讯录的逻辑
- contact.h 通讯录相关功能的函数声明
- contact.c 通讯录相关功能的函数实现
test.c
我们先创建一个菜单供用户选择
static void menu()
{
printf("******************************\n");
printf("**** 1.add 2.del ****\n");
printf("*** 3.search 4.modfy****\n");
printf("*** 5.show 6.sort ***\n");
printf("*** 0.exit ***\n");
printf("******************************\n");
}
然后创建一个枚举类型对应菜单的数据,方便使用switch时看过去更明了。
enum Option
{
EXIT, //退出
ADD, //增加
DEL, //删除
SRARCH, //查找
MODFY, //修改
SHOW, //显示
SORT //排序
};
然后在main函数里面创建一个通讯录的变量(这里的结构体我在contact.h里面定义了)和大概框架给写好。
int main()
{
int input = 0;
struct Contact con;//创建了一个描述通讯录的变量
InitContact(&con);//初始化通讯录
do
{
menu();//菜单
printf("请选择:");
scanf("%d",&input);
switch (input)
{
case EXIT:
printf("退出通讯录\n");
break;
case ADD:
Addcontact(&con);//增加联系人
break;
case DEL:
DelContact(&con);//删除联系人
break;
case SRARCH:
SrarchContact(&con);//查找联系人
break;
case MODFY:
ModfyContact(&con);//修改通讯录
break;
case SHOW:
ShowCotact(&con);//显示通讯录
break;
case SORT:
SortContact(&con);//排序通讯录
break;
default:
printf("选择错误,请重新选择\n");
}
} while (input);
return 0;
}
contact.h
在创建的头文件里把需要的头文件加上,这样其他两个.c文件只需要声明我们自己创建的头文件就可以使用库函数了,然后创建一个结构体来描述一个联系人的信息,用**#define**定义常量,可以更方便的修改。
再创建一个结构体,里面创建一个结构体数组,数组里面存放1000个联系人的信息,再创建一个整型变量,用来记录当前存放了多少个人的信息。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define NAME_MAX 20 //名字
#define SEX_MAX 5 //性别
#define TELE_MAX 12 //电话
#define ADDR_MAX 30 //地址
#define DATA_MAX 1000//人数
struct PeoInfo //描述一个人信息的结构体
{
char name[NAME_MAX];//名字
int age;//年龄
char sex[SEX_MAX];//性别
char tele[TELE_MAX];//电话
char addr[ADDR_MAX];//地址
};
//通讯录的结构体
struct Contact
{
struct PeoInfo data[DATA_MAX];
int sz;//记录通讯录中里有几个人的信息
};
接下来就是我们需要实现的功能函数声明。
void InitContact(struct Contact* con);//初始化通讯录
void Addcontact(struct Contact* con);//增加联系人
void ShowCotact(const struct Contact* con);//显示通讯录
void DelContact(struct Contact* con);//删除联系人
void SrarchContact(struct Contact* con);//查找联系人
void ModfyContact(struct Contact* con);//修改通讯录
void SortContact(struct Contact* con);//排序通讯录
contact.c
初始化通讯录
我们创建好数组后其实里面的数值都是些随机数,我们需要将记录联系人的整型变量置0,然后把数组的元素全部置0,这里我用的是memset库函数。
void InitContact(struct Contact* con)
{
con->sz = 0;
//memset -设置内存的函数
memset(con->data, 0, sizeof(con->data));
}
增加联系人
增加联系人之前我们需要判断通讯录是否满了,如果满了就无法添加,这里#define定义的常量就用上了。没满就开始添加数据,记录联系人的变量刚好可以对应上添加数据数组的下标,每次添加完成记录联系人的变量+1。
void Addcontact(struct Contact* con)
{
if (con->sz == DATA_MAX)
{
printf("通讯录已满,无法继续添加\n");
}
else
{
printf("添加联系人\n");
printf("请输入姓名:");
scanf("%s", con->data[con->sz].name);
printf("请输入年龄:");
scanf("%d", &con->data[con->sz].age);
printf("请输入性别:");
scanf("%s", con->data[con->sz].sex);
printf("请输入电话:");
scanf("%s", con->data[con->sz].tele);
printf("请输入地址:");
scanf("%s", con->data[con->sz].addr);
con->sz++;
printf("添加成功\n");
}
}
运行示例
显示联系人
添加联系人后我们想知道是否添加成功了,这时就可以写显示联系人的功能来测试是否添加成功。显示通讯录只需要遍历一遍数组打印出来就行了。
void ShowCotact(const struct Contact* con)
{
int i = 0;
printf("显示通讯录\n");
if (con->sz == 0)
{
printf("通讯录为空\n");
return;
}
printf("%-15s\t%-5s\t%-5s\t%-12s\t%-20s\t\t\n","姓名","年龄","性别","电话","地址");
for (i = 0; i < con->sz; i++)
{
printf("%-15s\t", con->data[i].name);
printf("%-5d\t", con->data[i].age);
printf("%-5s\t", con->data[i].sex);
printf("%-12s\t", con->data[i].tele);
printf("%-20s\t\n", con->data[i].addr);
}
}
运行示例
删除联系人
在删除联系人之前我们要先找那个联系人才能删除,如果找不到则无法删除,这里我创建了一个查找的函数,如果找到了就返回下标,如果找不到就返回-1。
//查找
int FindByName(struct Contact* con, char name[])//找到返回下标,没找到返回-1
{
int i = 0;
for (i = 0; i < con->sz; i++)
{
if (strcmp(con->data[i].name, name) == 0)
{
return i;
}
}
return -1;
}
另外,在删除函数里面,我增加了一个菜单,可以选择删除指定联系人或者清空通讯录,如果删除值定联系人则记录联系人个数的变量要-1,清空则直接置0。
void DelMeum()
{
printf("***************************\n");
printf("**** 1.删除指定联系人 ****\n");
printf("**** 2.清空通讯录 ****\n");
printf("***************************\n");
}
void DelContact(struct Contact* con)//删除联系人
{
char name[NAME_MAX] = {
0 };
printf("删除联系人\n");
if (con->sz == 0)
{
printf("通讯录为空\n");
}
else
{
int input = 0;
DelMeum();
printf("请选择:>");
scanf("%d", &input);
if (input == 1)
{
printf("请输入要删除人的名字:");
scanf("%s", name);
//查找
int pos = FindByName(con, name);//找到返回下标,没找到返回-1
if (pos == -1)
{
printf("要删除的人不存在\n");
}
else
{
//删除
int j = 0;
for (j = 0; j < con->sz - 1; j++)
{
con->data[j] = con->data[j + 1];
}
con->sz--;
printf("删除成功\n");
}
}
else if (input == 2)
{
memset(con->data, 0, sizeof(struct PeoInfo));
con->sz = 0;
printf("清空通讯录成功\n");
}
}
}
运行示例
查找联系人
查找联系人,刚好利用了上面写的查找代码,找到就打印出来,没找到就输出被查找人不存在。
void SrarchContact(struct Contact* con)//查找联系人
{
printf("查找联系人\n");
char name[NAME_MAX] = {
0 };
printf("请输入要查找人的姓名:");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
}
else
{
printf("%-15s\t%-5s\t%-5s\t%-12s\t%-20s\t\t\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%-15s\t", con->data[pos].name);
printf("%-5d\t", con->data[pos].age);
printf("%-5s\t", con->data[pos].sex);
printf("%-12s\t", con->data[pos].tele);
printf("%-20s\t\n", con->data[pos].addr);
}
}
运行示例
修改联系人
修改联系人也用到了查找函数,找到了就进行修改,找不到就输出通讯录没有该联系人。
void ModfyContact(struct Contact* con)//修改通讯录
{
char name[NAME_MAX] = {
0 };
printf("修改联系人\n");
printf("请输入要修改的联系人名字:");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos == -1)
{
printf("通讯录没有该联系人\n");
}
else
{
printf("请输入要修改的姓名:");
scanf("%s", con->data[pos].name);
printf("请输入要修改的年龄:");
scanf("%d", &con->data[pos].age);
printf("请输入要修改的性别:");
scanf("%s", con->data[pos].sex);
printf("请输入要修改的电话:");
scanf("%s", con->data[pos].tele);
printf("请输入要修改的地址:");
scanf("%s", con->data[pos].addr);
printf("修改成功\n");
}
}
运行示例
排序联系人
排序联系人可以根据用户选择按年龄排序还是按名字排序,我这里用的是库函数qsort排序的。
static void menu()
{
printf("***************************\n");
printf("**** 1.name ****\n");
printf("**** 2.age ****\n");
printf("***************************\n");
}
enum Choice //选择
{
NOTSORT,
NAME,
AGE
};
int cmp_name(const void* e1,const void* e2)
{
return strcmp(((struct Contact*)e1)->data->name, ((struct Contact*)e2)->data->name);
}
int cmp_age(const void* e1,const void* e2)
{
return (((struct Contact*)e1)->data->age - ((struct Contact*)e2)->data->age);
}
void SortContact(struct Contact* con)//排序通讯录
{
int input = 0;
menu();
printf("请选择您需要的排序方式:>");
scanf("%d", &input);
switch (input)
{
case NAME:
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_name);
printf("按名字排序成功\n");
break;
case AGE:
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
printf("按年龄排序成功\n");
break;
case NOTSORT:
printf("取消排序");
break;
default:
printf("选择错误\n");
break;
}
}
运行示例
以上就是通讯录所需功能实现的全部代码
总结
静态版通讯录的空间是一开始就给定的,如果空间满了又不能增加空间,而如果使用的空间并没有那么大则又造成了浪费空间的尴尬处境,后续我将会写一篇动态版的通讯录,动态版通讯录能解决这种尴尬情况,谢谢各位观看!