目录
普通版
功能需求
模块设计
test.c模块实现
contact.h模块实现
类型的声明
函数的声明
头文件、枚举、宏定义
contact.c 模块实现
初始化通讯录
增加联系人
显示所有联系人的信息
查找函数
删除指定联系人
查找指定联系人
修改指定联系人
进阶版通讯录(动态存储)
模块一test.c
模块二Contact.h
模块三Contact.c
实现通讯录的增加、删除、查找、修改、显示
分为三个模块
test.c 测试通讯录
contact.h 函数和类型的声明
contact.c 函数的实现
首先我们得有我们的主函数
int main()
{
test();
return 0;
}
然后我们在实现test函数时,我们需要完成通讯录的显示菜单,还需要操作者可以进行选择
具体实现如下
void menu()
{
printf("*********** 通讯录 *************\n");
printf("******* 1 添加联系人 2 删除联系人 ******\n");
printf("******* 3 查找联系人 4 修改联系人 ******\n");
printf("******* 5 显示通讯录 0 退出通讯录 ******\n");
printf("*****************************************\n");
}
void test()
{
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 SEARCH :
SearchContact(&con);
break;
case MODIFY :
ModifyContact(&con);
break;
case SHOW :
ShowContact(&con);
break;
case EXIT :
printf("退出通讯录\n");
break;
default: printf("输入错误,重新输入\n");
break;
}
} while (input);
}
而在此处出现的结构体Contact与枚举会在contact.h模块进行声明,还有函数InitContact声明也会在contact.h说明,具体实现会在contact.c模块进行实现
//类型的声明
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
//通讯录
typedef struct Contact
{
PeoInfo data[MAX];
int sz;
}Contact;
sz存在的意义为可以知道通讯录里有多少联系人
//函数声明
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示所有联系人的信息
void ShowContact(const Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
#include
#include
#include
#include
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
enum OPTION//枚举
{
EXIT,//0
ADD,
DEL,
SEARCH,
MODIFY,
SHOW
};
void InitContact(Contact* pc)
{
assert(pc);//断言,防止pc为空指针
memset(pc->data, 0, sizeof(pc->data));//进行复制,每个字节都为0
pc->sz = 0;
}
这里注意我们需要我们需要进行判断如果通讯录已满,我们就得进行提醒
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz >= MAX)
{
printf("通讯录已满,无法添加");
return;
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功增加联系人\n");
}
注意数据与表头的对齐
void ShowContact(const Contact* pc)
{
assert(pc);
int i = 0;
//打印列标题
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
查找函数存在的意义:我们发现我们发现在删除、查找、修改函数实现中我们都会有查找这一项功能,而我们在这里进行统一实现,后续使用起来就会很方便
static int FindByName(const Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;//找到了
}
}
return -1;//找不到
}
这里的删除其实是后面的数据对前面的数据的覆盖
实现如下
void DelContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[MAX_NAME] = { 0 };
assert(pc);
//删除
printf("请输入要删除的人名字:>");
scanf("%s", name);
//找到要删除的人
int del = FindByName(pc, name);
if (del == -1)
{
printf("要删除的人不存在\n");
return;
}
int i = 0;
//删除坐标位del的联系人
for (i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("成功删除联系人\n");
}
只需要按名字进行查找,最后进行输出就好,实现如下
void SearchContact(const Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法查找\n");
return;
}
char name[MAX_NAME] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
printf("要查找的人不存在\n");
else
{
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
}
void ModifyContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法修改\n");
return;
}
char name[MAX_NAME] = { 0 };
printf("请输入要修改人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
printf("要修改的人不存在\n");
else
{
printf("请输入名字:>");
scanf("%s", pc->data[pos].name);
printf("请输入年龄:>");
scanf("%d", &(pc->data[pos].age));
printf("请输入性别:>");
scanf("%s", pc->data[pos].sex);
printf("请输入电话:>");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
}
进阶版通讯录实现与普通版通讯录区别在于,普通版通讯录的存储是有限,是提前规定好的,而进阶版则是可以根据用户的实际需求进行扩容。具体实现同样分为三个模块
此模块没有什么变化
#include "Contact.h"
void menu()
{
printf("*********** 通讯录 *************\n");
printf("******* 1 添加联系人 2 删除联系人 ******\n");
printf("******* 3 查找联系人 4 修改联系人 ******\n");
printf("******* 5 显示通讯录 0 退出通讯录 ******\n");
printf("*****************************************\n");
}
void test()
{
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 SEARCH :
SearchContact(&con);
break;
case MODIFY :
ModifyContact(&con);
break;
case SHOW :
ShowContact(&con);
break;
case EXIT :
printf("退出通讯录\n");
break;
default: printf("输入错误,重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
由于变为了动态存储所以这里的结构的声明有一些变化
#include
#include
#include
#include
#define DEFAULT_SZ 3
#define INC_SZ 2
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
enum OPTION//枚举
{
EXIT,//0
ADD,
DEL,
SEARCH,
MODIFY,
SHOW
};
//类型的声明
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
//通讯录
//修改后
typedef struct Contact
{
PeoInfo* data;//指向了存放数据的空间
int sz;//记录的当前放的有效元素的个数
int capacity;//通讯录当前的最大容量
}Contact;
//函数声明
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示所有联系人的信息
void ShowContact(const Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
修改如下
//静态版本
//void InitContact(Contact* pc)
//{
// assert(pc);
// memset(pc->data, 0, sizeof(pc->data));
// pc->sz = 0;
//}
//动态的版本
void InitContact(Contact* pc)
{
assert(pc);
memset(pc->data, 0, sizeof(pc->data));
pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
//静态版本
//
//void AddContact(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通讯录已满,无法添加\n");
// return;
// }
//
// printf("请输入名字:>");
// scanf("%s", pc->data[pc->sz].name);
// printf("请输入年龄:>");
// scanf("%d", &(pc->data[pc->sz].age));
// printf("请输入性别:>");
// scanf("%s", pc->data[pc->sz].sex);
// printf("请输入电话:>");
// scanf("%s", pc->data[pc->sz].tele);
// printf("请输入地址:>");
// scanf("%s", pc->data[pc->sz].addr);
//
// pc->sz++;
// printf("成功增加联系人\n");
//}
int CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ)*sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;
}
else
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
return 1;
}
}
return 1;
}
//动态的版本
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == MAX)
if (0 == CheckCapacity(pc))
{
printf("通讯录已满,无法添加\n");
return;
}
void AddContact(Contact* pc)
printf("成功增加联系人\n");
}
void ShowContact(const Contact* pc)
{
assert(pc);
void ModifyContact(Contact* pc)
}
}
//释放空间
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
若有需要完整版的宝子或者在使用时出现了一些问题,都可以评论区评论或私信博主!!!