本课题模拟通讯录的实现,包括:
1.增加联系人的信息
2.删除联系人
3.查找联系人
4.修改联系人信息
5.对联系人进行排序
本节目录:
通讯录的实现样貌展示:这就算通讯录的菜单
下面对每个功能进行模块性讲解。
【思路1】
通讯录是一个复杂的对象,包含了用户的名字、性别、年龄、电话号码和家庭住址等信息,所以需要用结构体来定义
#define NAME_MAX 20
#define SEX_MAX 6
#define TELE_MAX 20
#define ADDR_MAX 20
typedef struct PeoInfo
{
char name[NAME_MAX];//姓名
char sex[SEX_MAX];//性别
int age;//年龄
char tele[TELE_MAX];//电话
char addr[ADDR_MAX];//地址
}PeoInfo;
为了方便后续修改结构体中每个成员的大小范围,使用了宏定义的常量,来表示每个数组的大小。
【思路2】
(1)这是一个结构体类型,用来创造变量,一次只能创建一个,不合适,所以需要数组。
(2)因为通讯录是数组,所以需要一个变量来实时记录通讯录的个数。
(3)为了可以使用,他们需要同类型,所以还需要再创造一个结构体
#define MAX 100
typedef struct contact
{
PeoInfo data[MAX];//通讯录
int sz;//记录通讯录的个数
}contact;
接下来再用contact创造变量就好
contact con;//通讯录变量的创建
(1)需要修改通讯录中的内容,需要传结构体的地址
InitContact(&con);//传参
(2)初始化函数
void InitContact(contact* pc)
{
assert(pc);
memset(pc->data,0,sizeof(pc->data));
pc->sz = 0;//通讯录开始的容量为0
}
(1)用assert函数判断指针是否为空,为空则会退出程序。需要包含头文件:#include
(2)用memset函数将通讯录中的内容设置成0即可。需要包含头文件:#include
(1)信息添加的条件
在信息添加前我们需要查看通讯录是否已满,满了则不能再继续添加信息。
传参:
AddContact(&con);
通讯录判满:
void AddContact(contact* pc)
{
assert(pc);//指针判空操作
if (pc->sz == MAX)
{
printf("通讯录已满,存入信息失败\n");
return;
}
}
(2)信息添加的过程
void AddContact(contact* pc)
{
assert(pc);
if (pc->sz == MAX)
{
printf("通讯录已满,存入信息失败\n");
return;
}
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].tele);
printf("请输入住址>:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("信息添加成功\n");
}
(1)逐一对通讯录进行信息添加即可,需要注意结构体的访问方式
(2)data数组的第一个联系人的下标是0,等于sz的值
(3)信息添加的完善
以上的操作每次只能添加一个人的信息,很不方便。所以我们使用go语句循环以上的代码
void AddContact(contact* pc)
{
assert(pc);
int adds;
back://go语句标记2
if (pc->sz == MAX)
{
printf("通讯录已满,存入信息失败\n");
return;
}
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].tele);
printf("请输入住址>:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("信息添加成功\n");
//循环是否继续的判断
printf("是否继续添加联系人信息1/0:");
scanf("%d",&adds);
if (adds == 1)
goto back;//go语句标记1
else
{
return;
}
}
当已经可以想通讯录中添加了联系人信息之后,就可以将他们的信息打印在屏幕上进行验证:
(1)可以打印通讯录的条件
传参:
ShowContact(&con);
通讯录判空:
void ShowContact(contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
}
如果通讯录一个信息都没有,将不会打印
(2)通讯录的打印
void ShowContact(contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
printf("%-10s %-5s %-10s %-15s %-10s\n","名字","性别","年龄","电话","住址");
int i = 0;
for (i=0;isz;i++)
{
printf("%-10s %-5s %-10d %-15s %-10s\n",
pc->data[i].name, pc->data[i].sex, pc->data[i].age,
pc->data[i].tele, pc->data[i].addr);
}
printf("\n");
}
(1)通讯录打印的时候,注意打印的格式
(2)%-10s:实现的是左对齐
(1)通讯录的判空
传参:
DelContact(&con);
判空:
void DelContact(contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,删除失败\n");
return;
}
}
(2)删除联系人的条件
如果需要删除的联系人不存在,那么也将会删除失败。所以需要查找联系人是否存在
查找函数:(联系人存在,返回联系人的下标;不存在返回-1)
传参:
printf("请输入你要删除的联系人:");
char name[NAME_MAX];
scanf("%s",name);
int ret = FindContact(pc,name);
static int FindContact(contact* pc,char name[])
{
assert(pc);
int i = 0;
for (i=0;isz;i++)
{
if (strcmp(name, pc->data[i].name) == 0)
return i;
}
return -1;
}
(3)删除操作
void DelContact(contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,删除失败\n");
return;
}
printf("请输入你要删除的联系人:");
char name[NAME_MAX];
scanf("%s",name);
int ret = FindContact(pc,name);
if (ret == -1)
{
printf("联系人不存在,删除失败\n");
return;
}
int i = 0;
for (i=ret;isz-1;i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除联系人成功\n");
}
依然需要用到上述的查找某位联系人是否存在的函数
传参:
SearchContact(&con);
(1)先查找
void SearchContact(contact* pc)
{
assert(pc);
printf("请输入你要查找联系人的名字:");
char name[NAME_MAX];
scanf("%s", name);
int ret = FindContact(pc, name);
}
(2)后打印
联系人存在就打印该联系人的信息
void SearchContact(contact* pc)
{
assert(pc);
printf("请输入你要查找联系人的名字:");
char name[NAME_MAX];
scanf("%s", name);
int ret = FindContact(pc, name);
if (ret == -1)
{
printf("联系人不存在,查找失败\n");
return;
}
printf("查找成功:\n");
printf("%-10s %-5s %-10s %-15s %-10s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-10s %-5s %-10d %-15s %-10s\n",
pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
pc->data[ret].tele, pc->data[ret].addr);
}
想要修改某位联系人的信息,首先确定该联系人是否存在
传参:
ModifyContact(&con);
(1)查找联系人
void ModifyContact(contact* pc)
{
assert(pc);
printf("请输入你要查找联系人的名字:");
char name[NAME_MAX];
scanf("%s", name);
int ret = FindContact(pc, name);
if (ret == -1)
{
printf("联系人不存在,修改失败\n");
return;
}
}
(2)修改联系人信息
void ModifyContact(contact* pc)
{
assert(pc);
printf("请输入你要查找联系人的名字:");
char name[NAME_MAX];
scanf("%s", name);
int ret = FindContact(pc, name);
if (ret == -1)
{
printf("联系人不存在,修改失败\n");
return;
}
printf("联系人存在:");
printf("%-10s %-5s %-10d %-15s %-10s\n",
pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
pc->data[ret].tele, pc->data[ret].addr);
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].tele);
printf("请修改住址>:");
scanf("%s", pc->data[ret].addr);
printf("\n修改成功");
}
对联系人排序,使用库函数中的排序函数qsort,我们只需要完成比较函数即可。
排序可以按照名字的字典顺序或者年龄等,我们这里介绍名字和年龄的排序。
(1)按照名字排序
传参:
qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_name);
第四个为函数指针,指向的比较函数需要我们自己完成
名字的比较函数:
//名字排序
int qsort_cmp_name(const void* e1,const void* e2)
{
return strcmp((((contact*)e1)->data)->name, (((contact*)e2)->data)->name);
}
(1) 名字的字典顺序,其实就算字符串的比较。
(2)字符串比较需要用函数strcmp,头文件#include
(2)按照年龄排序
传参:
qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_age);
年龄的比较函数:
//年龄排序
int qsort_cmp_age(const void* e1,const void* e2)
{
return (((contact*)e1)->data)->age - (((contact*)e2)->data)->age;
}
(3)完整排序函数
void menu2()
{
printf("*************************\n");
printf("**** 1.名字 2.年龄 ****\n");
printf("*************************\n");
}
//联系人排序
void SortContact(contact* pc)
{
int input2;
menu2();
printf("请选择排序方式:");
scanf("%d",&input2);
switch (input2)
{
case 1:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_name);break;
case 2:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_age);break;
defualt:printf("选择错误\n");
break;
}
}
每进入一次该函数,只能排序一次,不需要设置循环
(1)主函数部分
enum Option
{
EXIT,//退出
ADD,//增加
DEL,//删除联系人
SEARCH,//查找联系人
MODIFY,//修改指定联系人
SHOW,//打印联系人
SORT,//分类
};
int main()
{
contact con;
InitContact(&con);
int input;
do
{
menu();
printf("请输入你的选择>:");
scanf("%d",&input);
switch (input)
{
case ADD:AddContact(&con);
break;
case DEL:DelContact(&con);
break;
case SEARCH:SearchContact(&con);
break;
case MODIFY:ModifyContact(&con);
break;
case SHOW:ShowContact(&con);
break;
case SORT:SortContact(&con);
break;
case EXIT:printf("你已选择退出程序\n");
break;
default:printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
【代码思路】
(1)do…while循环配合switch选择语句完成菜单的构造。可以供用户多次选择,直至退出
(2)在选择语句中
(2)菜单函数
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");
}
所谓的菜单,就算打印出来让我们看。具体的选项还是得由主函数部分实现。
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
#define NAME_MAX 20
#define SEX_MAX 6
#define TELE_MAX 20
#define ADDR_MAX 20
#define MAX 100
typedef struct PeoInfo
{
char name[NAME_MAX];//姓名
char sex[SEX_MAX];//性别
int age;//年龄
char tele[TELE_MAX];//电话
char addr[ADDR_MAX];//地址
}PeoInfo;
typedef struct contact
{
PeoInfo data[MAX];//通讯录
int sz;//记录通讯录的个数
}contact;
//函数的声明
//初始化
void InitContact(contact* pc);
//添加用户信息
void AddContact(contact* pc);
//打印通讯录
void ShowContact(contact* pc);
//删除联系人
void DelContact(contact* pc);
//查找某个联系人
void SearchContact(contact* pc);
//修改联系人
void ModifyContact(contact* pc);
//联系人排序
void SortContact(contact* pc);
//函数功能的实现
void InitContact(contact* pc)
{
assert(pc);
memset(pc->data,0,sizeof(pc->data));
pc->sz = 0;
}
void ShowContact(contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
printf("%-10s %-5s %-10s %-15s %-10s\n","名字","性别","年龄","电话","住址");
int i = 0;
for (i=0;isz;i++)
{
printf("%-10s %-5s %-10d %-15s %-10s\n",
pc->data[i].name, pc->data[i].sex, pc->data[i].age,
pc->data[i].tele, pc->data[i].addr);
}
printf("\n");
}
void AddContact(contact* pc)
{
assert(pc);
int adds;
back:
if (pc->sz == MAX)
{
printf("通讯录已满,存入信息失败\n");
return;
}
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].tele);
printf("请输入住址>:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("信息添加成功\n");
printf("是否继续添加联系人信息1/0:");
scanf("%d",&adds);
if (adds == 1)
goto back;
else
{
return;
}
}
//查看某个联系人是否存在
static int FindContact(contact* pc,char name[])
{
assert(pc);
int i = 0;
for (i=0;isz;i++)
{
if (strcmp(name, pc->data[i].name) == 0)
return i;
}
return -1;
}
//删除联系人
void DelContact(contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,删除失败\n");
return;
}
printf("请输入你要删除的联系人:");
char name[NAME_MAX];
scanf("%s",name);
int ret = FindContact(pc,name);
if (ret == -1)
{
printf("联系人不存在,删除失败\n");
return;
}
int i = 0;
for (i=ret;isz-1;i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除联系人成功\n");
}
//查找联系人
void SearchContact(contact* pc)
{
assert(pc);
printf("请输入你要查找联系人的名字:");
char name[NAME_MAX];
scanf("%s", name);
int ret = FindContact(pc, name);
if (ret == -1)
{
printf("联系人不存在,查找失败\n");
return;
}
printf("查找成功:\n");
printf("%-10s %-5s %-10s %-15s %-10s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-10s %-5s %-10d %-15s %-10s\n",
pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
pc->data[ret].tele, pc->data[ret].addr);
}
//修改联系人
void ModifyContact(contact* pc)
{
assert(pc);
printf("请输入你要查找联系人的名字:");
char name[NAME_MAX];
scanf("%s", name);
int ret = FindContact(pc, name);
if (ret == -1)
{
printf("联系人不存在,修改失败\n");
return;
}
printf("联系人存在:");
printf("%-10s %-5s %-10d %-15s %-10s\n",
pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age,
pc->data[ret].tele, pc->data[ret].addr);
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].tele);
printf("请修改住址>:");
scanf("%s", pc->data[ret].addr);
printf("\n修改成功");
}
//分类菜单
void menu2()
{
printf("*************************\n");
printf("**** 1.名字 2.年龄 ****\n");
printf("*************************\n");
}
//名字排序
int qsort_cmp_name(const void* e1,const void* e2)
{
return strcmp((((contact*)e1)->data)->name, (((contact*)e2)->data)->name);
}
//年龄排序
int qsort_cmp_age(const void* e1,const void* e2)
{
return (((contact*)e1)->data)->age - (((contact*)e2)->data)->age;
}
//联系人排序
void SortContact(contact* pc)
{
int input2;
menu2();
printf("请选择排序方式:");
scanf("%d",&input2);
switch (input2)
{
case 1:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_name);break;
case 2:qsort(pc->data, pc->sz, sizeof(pc->data[0]), qsort_cmp_age);break;
defualt:printf("选择错误\n");
break;
}
}
//主函数及菜单
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");
}
enum Option
{
EXIT,//退出
ADD,//增加
DEL,//删除联系人
SEARCH,//查找联系人
MODIFY,//修改指定联系人
SHOW,//打印联系人
SORT,//分类
};
int main()
{
contact con;
InitContact(&con);
int input;
do
{
menu();
printf("请输入你的选择>:");
scanf("%d",&input);
switch (input)
{
case ADD:AddContact(&con);
break;
case DEL:DelContact(&con);
break;
case SEARCH:SearchContact(&con);
break;
case MODIFY:ModifyContact(&con);
break;
case SHOW:ShowContact(&con);
break;
case SORT:SortContact(&con);
break;
case EXIT:printf("你已选择退出程序\n");
break;
default:printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
至此,通讯录的实现完成。