目录
一,项目结构分析
二,项目文件划分
2.1 头文件(contact.h)
2.2 源文件
三,前期准备
3.1,创建联系人类
3.2,创建通信录类
四,基本功能实现
4.1 初始化通讯录
4.2 添加联系人
4.3 删除联系人
4.4 查找功能
4.5,修改联系人信息
4.6,排序功能
4.7 添加黑名单
4.8 打印输出功能
4.9 函数销毁
五,主函数框架
六,项目源码
6.1,contact.h文件
6.2,contact.c文件
6.3,test.c文件
一,项目结构分析
我用思维导图的方式来展示我编写的通讯录所具有的功能:
二,项目文件划分
2.1 头文件(contact.h)
#pragma once
//库函数
#include
#include
#include
#include
//宏定义,方便后期修改数值时不用依次修改
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 20
#define MAX_ADD 10
#define DEFAUT_SZ 3;//初始化通讯录的容量为3人
///
///可以储存1000个联系人信息的
///
typedef struct Peoinfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
char tele[MAX_SEX];
int age;
char add[MAX_ADD];//地址
}Peoinfo;
//为了方便起见再定义一个结构体去更好地表示
typedef struct Contact
{
Peoinfo* data;
Peoinfo* Special_concern;//设置特别关心
Peoinfo* Blacklist;//加入黑名单
int sp;//实时记录特别关心的人数
int bl;//实时记录黑名单的人数
int capacity;//记录通讯录当前的最大容量
int sz;//实时通讯录的人数的大小
}Contact;
/*枚举顾名思义就是一一列举。
把可能的取值一一列举。*/
enum Opertation//enum->枚举,将可能拥有的功能都列举出来,在后面可以直接使用
{
EXIT, //退出程序
ADD, //添加联系人
DEL, //删除联系人
SEARCH, //查找联系人
MODIFY, //修改联系人信息
SORT, //排序
PRINT, //打印/展示
ADDBlacklist, //添加黑名单
};//
//函数声明
//初始化通讯录
void InitContact(Contact* pc);
//销毁通讯录
void DestroyContact(Contact* pc);
//添加联系人
void AddContact(Contact* pc);
void Blacklist(Contact* pc);
//展示所有联系人
void PrintContact(Contact* pc);
//删除联系人
void DelContact(Contact* pc);
//修改指定联系人的信息
void ModifyContact(Contact* pc);
//查找联系人信息
void SearchContact(Contact* pc);
//联系人排序
void SortContact(Contact* pc);
//寻找人名函数
//多个函数都需要查找联系人的位置,为了方便起见,选择直接定义一个查找函数
int Find(Contact* pc, char* name);
头文件的主要作用就是对于整个项目可能用到的头文件进行包含,其次就是各种类型的声明以及函数的声明。
2.2 源文件
源文件包括contact.c以及test.c:
contact.c文件主要是对于一些功能函数的实现(头文件中枚举所给出的功能)
test.c文件就是主函数所在的文件,是整个项目的执行框架。
三,前期准备
3.1,创建联系人类
typedef struct Peoinfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
char tele[MAX_TELE];
int age;
char add[MAX_ADD];//地址
}Peoinfo;
联系人的结构体类的功能就十分的明确,包含着一个联系人所有的属性:姓名,年龄,性别,电话,地址。
其中的[MAX_NAME],[MAX_SEX],[MAX_TELE],[MAX_ADD],都是在头文件中经过#define定义后的。
3.2,创建通信录类
//为了方便起见再定义一个结构体去更好地表示
typedef struct Contact
{
Peoinfo* data;
Peoinfo* Special_concern;//设置特别关心
Peoinfo* Blacklist;//加入黑名单
int sp;//实时记录特别关心的人数
int bl;//实时记录黑名单的人数
int capacity;//记录通讯录当前的最大容量
int sz;//实时通讯录的人数的大小
}Contact;
通信录类的成员大致分为两个板块:1.结构体变量 2.整型变量
1.结构体变量: 联系人类的结构体,特别关心的结构体,黑名单的结构体
2.整型变量:实时记录通讯录人数,实时记录特别关心人数,实时记录黑名单人数,记录通讯录当前最大的容量这里运用了结构体的嵌套,因为对于通信录而言,其自身包含有很多的属性,而联系人又有许多的属性,所以我们不能将他们塞进同一个结构体中,只能是分别建立结构体,让后嵌套让二者关联起来,这样结构也会更加清晰。
四,基本功能实现
4.1 初始化通讯录
//初始化通讯录
void InitContact(Contact* pc)
{
assert(pc);
pc->capacity = DEFAUT_SZ;
pc->data = (Peoinfo*)malloc(sizeof(Peoinfo) * (pc->capacity));
pc->Special_concern = (Peoinfo*)malloc(sizeof(Peoinfo) * (pc->capacity));
pc->Blacklist = (Peoinfo*)malloc(sizeof(Peoinfo) * (pc->capacity));
if (pc->data == NULL && pc->Special_concern == NULL && pc->Blacklist == NULL)
{
perror("InitContact::malloc:");
return;
}
pc->sz = 0;
pc->sp = 0;
pc->bl = 0;
memset(pc->data, 0, sizeof(Peoinfo*) * pc->capacity);
memset(pc->Special_concern, 0, sizeof(Peoinfo*) * pc->capacity);
memset(pc->Blacklist, 0, sizeof(Peoinfo*) * pc->capacity);
}
对于一个通信录来说,最开始是没有初值的,所以需要我们来进行初始化,这里的初始化我们运用的是内存操作函数memset(),这样可以快速的进行初始化。可能有人会想怎么不直接大括号给它赋值为0,更加简单,首先这里我们将其包装成一个函数是为了长远的考虑,假如未来我们不能简单的给他初始化为0呢,那还是需要用函数的。
4.2 添加联系人
//添加联系人
void AddContact(Contact* pc)
{
CheckCapacity(pc);//增容
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].add);
printf("是否需要设为特别关心(1.Yes/0.No):");
int set = 0;
against:
scanf("%d", &set);
if (set == 1)
{
memcpy(pc->Special_concern[pc->sp].name, pc->data[pc->sz].name, sizeof(pc->data[pc->sz].name));
memcpy(pc->Special_concern[pc->sp].sex, pc->data[pc->sz].sex, sizeof(pc->data[pc->sz].sex));
memcpy(pc->Special_concern[pc->sp].tele, pc->data[pc->sz].tele, sizeof(pc->data[pc->sz].tele));
memcpy(pc->Special_concern[pc->sp].add, pc->data[pc->sz].add, sizeof(pc->data[pc->sz].add));
pc->Special_concern[pc->sp].age = pc->data[pc->sz].age;
pc->sp++;
printf("特别关心添加成功!\n");
}
else if(set == 0)
{
pc->sz++;
printf("添加联系人成功\n\n");
return;
}
else
{
printf("输入错误!请重新输入:");
goto against;
}
pc->sz++;
printf("添加联系人成功\n\n");
}
添加联系人的函数的本质逻辑很简单,就是scanf函数输入然后赋值,然后每添加一个联系人的完整信息后,那个记录人数的变量就自增
但是我们可以看到我们还给定了一个函数CheckCapacity(pc);//增容
因为我们是动态内存分配且我们给定的通讯录初始容量为3人,会出现容量不够的情况,这时我们就需要进行扩容了,而CheckCapacity(pc)函数就是来在添加联系人前检查容量是否已满,如满则扩容!
void CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
//增容
Peoinfo* tmp = (Peoinfo*)realloc(pc->data, sizeof(Peoinfo) * (pc->capacity + 2));
if (tmp != NULL)
{
pc->data = tmp;
}
else
{
perror("CheckCapacity::realloc:");
return;
}
pc->capacity += 2;
printf("增容成功\n");
}
}
4.3 删除联系人
//删除联系人:只需要提供姓名
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
}
printf("请输入要删除的联系人姓名:");
char name[MAX_NAME];//定义一个需要删除的联系人,后面去比对
scanf("%s", &name);
int ret = Find(pc, name);//得到需要删除联系人下下标,方便后续删除
if (ret == -1)
{
printf("没有找到要删的联系人\n");
return;
}
else
{
int i = 0;
for (i = ret; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];//从需要删除的联系人开始向后赋值,将data[i]=data[i+1],到下标为sz-1的地方
}
}
pc->sz--;//实时更改sz的大小
}
删除的基本逻辑就是先找到人,然后进行覆盖删除。这里因为后面的修改,查找都是需要找到特定的联系人的,所以我们会先定义一个专门用来查找的函数,也就是Find函数。
查找函数会去遍历那个储存联系人的结构体数组,一个个的与你想查找的联系人名进行对比,找到了就返回下标,找不到就返回-1。
//寻找人名函数
//多个函数都需要查找联系人的位置,为了方便起见,选择直接定义一个查找函数
int Find(Contact* pc, char* name)
{
assert(pc);
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;//找到返回下标
}
}
return -1;//找不到返回-1
}
4.4 查找功能
//通过人名查找信息
void Search_by_num(Contact* pc)
{
printf("请输入要查找的联系人:");
char name[MAX_NAME];
scanf("%s", &name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("没有找到该联系人\n");
return;
}
else
{
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].add);
}
}
//通过号码查找信息
void Search_by_tale(Contact* pc)
{
printf("请输入联系人的号码:");
char tele[MAX_TELE];
scanf("%s", tele);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
int ret = i;
if (strcmp(pc->data[i].tele, tele) == 0)
{
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].add);
}
}
if (i == pc->sz - 1)
{
printf("未找到该联系人的信息!\n");
}
}
//通过地址来查找信息
void Search_by_add(Contact* pc)
{
printf("请输入联系人的地址:");
char add[MAX_ADD];//地址
scanf("%s", add);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
int ret = i;
if (strcmp(pc->data[i].add, add) == 0)
{
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].add);
}
}
if (i == pc->sz - 1)
{
printf("未找到该联系人的信息!\n");
}
}
//查找联系人
void SearchContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
}
printf("请输入以什么内容来查找联系人(1.姓名/2.电话/3.地址):");
int num = 0;
scanf("%d", &num);
switch (num)
{
case 1:
Search_by_num(pc);
break;
case 2:
Search_by_tale(pc);
break;
case 3:
Search_by_add(pc);
break;
default:
printf("输入错误!\n");
break;
}
}
查找功能函数的逻辑就是运用上面所说的查找函数,找到特定的联系人的下标后,对指定的联系人信息进行打印就可。
4.5,修改联系人信息
//修改通讯录的信息
void ModifyContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
}
printf("请输入要替换的联系人:");
char name[MAX_NAME];
scanf("%s", &name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("没有找到要替换的联系人\n");
return;
}
else
{
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].add);
printf("修改成功\n");
}
}
修改函数的基本逻辑就是先得找到特定的人,运用查找函数拿到下标后,在对信息进行修改就可。
4.6,排序功能
//自定义比较函数
int Comparestu(const void* e1, const void* e2) {
return ((struct Peoinfo*)e1)->age - ((struct Peoinfo*)e2)->age;//以年龄作为比较对象
}
//排序函数
void SortContact(Contact* pc) {
//这里的排序我们可以用qsort来实现
qsort(pc->data, pc->sz, sizeof(pc->data[0]), Comparestu);
printf("排序完毕,可使用打印查看!\n");
}
对于排序,这里是以年龄为依据进行排序的,主要实现方法是运用了qsort函数进行排序,qsort函数需要有一个自定义的比较函数,所以同时也定义了一个比较函数,当比较的而言前者较大时,返回值大于0,qsort函数就会对比较的二者进行交换。当然,qsort函数的底层原理实现博主之前的文章就有,大家不懂的可以去看看。
4.7 添加黑名单
//添加黑名单
void Blacklist(Contact* pc)
{
printf("\n1.姓名/2.电话号码:");
int choose = 0;
scanf("%d", &choose);
if (choose == 1)
{
printf("请输入您想加入黑名单的联系人的姓名:");
char name[MAX_NAME];
scanf("%s", name);
for (int i = 0;i < pc->sz;i++)
{
if (strcmp(name, pc->data[i].name) == 0)
{
memcpy(pc->Blacklist[pc->bl].name, pc->data[i].name, sizeof(pc->data[i].name));
memcpy(pc->Blacklist[pc->bl].sex, pc->data[i].sex, sizeof(pc->data[i].sex));
memcpy(pc->Blacklist[pc->bl].tele, pc->data[i].tele, sizeof(pc->data[i].tele));
memcpy(pc->Blacklist[pc->bl].add, pc->data[i].add, sizeof(pc->data[i].add));
pc->Blacklist[pc->bl].age = pc->data[i].age;
int ret = Find(pc, name);//得到需要删除联系人下下标,方便后续删除
for (int j = ret; j < pc->sz - 1; j++)
{
pc->data[j] = pc->data[j + 1];//从需要删除的联系人开始向后赋值,将data[i]=data[i+1],到下标为sz-1的地方
}
pc->sz--;
pc->bl++;
}
}
}
if (choose == 2)
{
printf("请输入您想加入黑名单的联系人的电话号码:");
char tele[MAX_NAME];
scanf("%s", tele);
for (int i = 0;i < pc->sz;i++)
{
if (strcmp(tele, pc->data[i].tele) == 0)
{
memcpy(pc->Blacklist[pc->bl].name, pc->data[i].name, sizeof(pc->data[i].name));
memcpy(pc->Blacklist[pc->bl].sex, pc->data[i].sex, sizeof(pc->data[i].sex));
memcpy(pc->Blacklist[pc->bl].tele, pc->data[i].tele, sizeof(pc->data[i].tele));
memcpy(pc->Blacklist[pc->bl].add, pc->data[i].add, sizeof(pc->data[i].add));
pc->Blacklist[pc->bl].age = pc->data[i].age;
int ret = Find(pc, tele);//得到需要删除联系人下下标,方便后续删除
for (int j = ret; j < pc->sz - 1; j++)
{
pc->data[j] = pc->data[j + 1];//从需要删除的联系人开始向后赋值,将data[i]=data[i+1],到下标为sz-1的地方
}
pc->sz--;
pc->bl++;
}
}
}
}
主要是通过再定义一个结构体来表示黑名单即可,再使用memcpy内存操作函数去赋值即可
4.8 打印输出功能
//打印/显示通讯录
//6.打印
void PrintContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
}
printf("\n1.总通讯录页面 2.特别关心页面 3.黑名单页面\n");
printf("请选择:");
int choose = 0;
scanf("%d", &choose);
switch (choose)
{
case 1:
printf("\n总通讯录页面\n");
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].add);
}
break;
case 2:
printf("\n 特别关心页面\n");
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->sp; i++)
{
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->Special_concern[i].name,
pc->Special_concern[i].sex,
pc->Special_concern[i].age,
pc->Special_concern[i].tele,
pc->Special_concern[i].add);
}
break;
case 3:
printf("\n 黑名单页面\n");
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->bl; i++)
{
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->Blacklist[i].name,
pc->Blacklist[i].sex,
pc->Blacklist[i].age,
pc->Blacklist[i].tele,
pc->Blacklist[i].add);
}
break;
default:
printf("目前还未开设其余页面!\n");
break;
}
}
打印功能是最简单的函数,逻辑就是遍历联系人的结构体数组,然后把每一个联系人的信息进行格式化的输出就行,在这里我们给定了三个选项(1.总通讯录页面 2.特别关心页面 3.黑名单页面)来供使用者选择
4.9 函数销毁
//销毁通讯录
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
free(pc->Special_concern);
pc->Special_concern = NULL;
pc->capacity = 0;;
pc->sz = 0;
pc->sp = 0;
printf("销毁成功!");
}
还是再说一次,因为我们使用动态内存操作去开辟空间(即malloc,realloc),在最后需要用free去销毁开辟的内存,即交还给计算机
五,主函数框架
#include "contact.h"
void meun()//菜单
{
printf("********************************************\n");
printf("*************** 〇退出程序 ***************\n");
printf("************ ①添加联系人信息 ************\n");
printf("************ ②删除联系人信息 ************\n");
printf("************ ③查询联系人信息 ************\n");
printf("************ ④修改联系人信息 ************\n");
printf("*********** ⑤给联系人信息排序 ***********\n");
printf("************ ⑥展示联系人信息 ************\n");
printf("************* ⑦添加黑名单 ***************\n");
printf("********************************************\n");
}
void test()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
meun();
printf("\n请输入:");
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 SORT:
SortContact(&con);
break;
case PRINT:
PrintContact(&con);
break;
case ADDBlacklist:
Blacklist(&con);
break;
case EXIT:
DestroyContact(&con);
break;
default:
printf("该选项不存在!\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
主函数首先就是菜单函数输出,用户根据菜单提示进行选择,选择的值会对应着后面switch结构的相应case语句,然后执行相应的函数。
这里case语句后面我们跟着的是枚举常量,枚举常量是有值的,既可以对应相应的功能代号,又可以让代码可读性更高,让人一看就知道某个case后面的功能是干什么的。
六,项目源码
6.1,contact.h文件
#pragma once
//库函数
#include
#include
#include
#include
//宏定义,方便后期修改数值时不用依次修改
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 20
#define MAX_ADD 10
#define DEFAUT_SZ 3;//初始化通讯录的容量为3人
///
///可以储存多个联系人信息:即在初始化3人的基础上满则加
///
typedef struct Peoinfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
char tele[MAX_TELE];
int age;
char add[MAX_ADD];//地址
}Peoinfo;
//为了方便起见再定义一个结构体去更好地表示
typedef struct Contact
{
Peoinfo* data;
Peoinfo* Special_concern;//设置特别关心
Peoinfo* Blacklist;//加入黑名单
int sp;//实时记录特别关心的人数
int bl;//实时记录黑名单的人数
int capacity;//记录通讯录当前的最大容量
int sz;//实时通讯录的人数的大小
}Contact;
/*枚举顾名思义就是一一列举。
把可能的取值一一列举。*/
enum Opertation//enum->枚举,将可能拥有的功能都列举出来,在后面可以直接使用
{
EXIT, //退出程序
ADD, //添加联系人
DEL, //删除联系人
SEARCH, //查找联系人
MODIFY, //修改联系人信息
SORT, //排序
PRINT, //打印/展示
ADDBlacklist, //添加黑名单
};//
//函数声明
//初始化通讯录
void InitContact(Contact* pc);
//销毁通讯录
void DestroyContact(Contact* pc);
//添加联系人
void AddContact(Contact* pc);
void Blacklist(Contact* pc);
//展示所有联系人
void PrintContact(Contact* pc);
//删除联系人
void DelContact(Contact* pc);
//修改指定联系人的信息
void ModifyContact(Contact* pc);
//查找联系人信息
void SearchContact(Contact* pc);
//联系人排序
void SortContact(Contact* pc);
//寻找人名函数
//多个函数都需要查找联系人的位置,为了方便起见,选择直接定义一个查找函数
int Find(Contact* pc, char* name);
6.2,contact.c文件
#include"contact.h"
//初始化通讯录
void InitContact(Contact* pc)
{
assert(pc);
pc->capacity = DEFAUT_SZ;
pc->data = (Peoinfo*)malloc(sizeof(Peoinfo) * (pc->capacity));
pc->Special_concern = (Peoinfo*)malloc(sizeof(Peoinfo) * (pc->capacity));
pc->Blacklist = (Peoinfo*)malloc(sizeof(Peoinfo) * (pc->capacity));
if (pc->data == NULL && pc->Special_concern == NULL && pc->Blacklist == NULL)
{
perror("InitContact::malloc:");
return;
}
pc->sz = 0;
pc->sp = 0;
pc->bl = 0;
memset(pc->data, 0, sizeof(Peoinfo*) * pc->capacity);
memset(pc->Special_concern, 0, sizeof(Peoinfo*) * pc->capacity);
memset(pc->Blacklist, 0, sizeof(Peoinfo*) * pc->capacity);
}
//销毁通讯录
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
free(pc->Special_concern);
pc->Special_concern = NULL;
pc->capacity = 0;;
pc->sz = 0;
pc->sp = 0;
printf("销毁成功!");
}
void CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
//增容
Peoinfo* tmp = (Peoinfo*)realloc(pc->data, sizeof(Peoinfo) * (pc->capacity + 2));
if (tmp != NULL)
{
pc->data = tmp;
}
else
{
perror("CheckCapacity::realloc:");
return;
}
pc->capacity += 2;
printf("增容成功\n");
}
}
//添加联系人
void AddContact(Contact* pc)
{
CheckCapacity(pc);//增容
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].add);
printf("是否需要设为特别关心(1.Yes/0.No):");
int set = 0;
against:
scanf("%d", &set);
if (set == 1)
{
memcpy(pc->Special_concern[pc->sp].name, pc->data[pc->sz].name, sizeof(pc->data[pc->sz].name));
memcpy(pc->Special_concern[pc->sp].sex, pc->data[pc->sz].sex, sizeof(pc->data[pc->sz].sex));
memcpy(pc->Special_concern[pc->sp].tele, pc->data[pc->sz].tele, sizeof(pc->data[pc->sz].tele));
memcpy(pc->Special_concern[pc->sp].add, pc->data[pc->sz].add, sizeof(pc->data[pc->sz].add));
pc->Special_concern[pc->sp].age = pc->data[pc->sz].age;
pc->sp++;
printf("特别关心添加成功!\n");
}
else if(set == 0)
{
pc->sz++;
printf("添加联系人成功\n\n");
return;
}
else
{
printf("输入错误!请重新输入:");
goto against;
}
pc->sz++;
printf("添加联系人成功\n\n");
}
//添加黑名单
void Blacklist(Contact* pc)
{
printf("\n1.姓名/2.电话号码:\n");
int choose = 0;
scanf("%d", &choose);
if (choose == 1)
{
printf("请输入您想加入黑名单的联系人的姓名:");
char name[MAX_NAME];
scanf("%s", name);
for (int i = 0;i < pc->sz;i++)
{
if (strcmp(name, pc->data[i].name) == 0)
{
memcpy(pc->Blacklist[pc->bl].name, pc->data[i].name, sizeof(pc->data[i].name));
memcpy(pc->Blacklist[pc->bl].sex, pc->data[i].sex, sizeof(pc->data[i].sex));
memcpy(pc->Blacklist[pc->bl].tele, pc->data[i].tele, sizeof(pc->data[i].tele));
memcpy(pc->Blacklist[pc->bl].add, pc->data[i].add, sizeof(pc->data[i].add));
pc->Blacklist[pc->bl].age = pc->data[i].age;
int ret = Find(pc, name);//得到需要删除联系人下下标,方便后续删除
for (int j = ret; j < pc->sz - 1; j++)
{
pc->data[j] = pc->data[j + 1];//从需要删除的联系人开始向后赋值,将data[i]=data[i+1],到下标为sz-1的地方
}
pc->sz--;
pc->bl++;
}
}
}
if (choose == 2)
{
printf("请输入您想加入黑名单的联系人的电话号码:");
char tele[MAX_NAME];
scanf("%s", tele);
for (int i = 0;i < pc->sz;i++)
{
if (strcmp(tele, pc->data[i].tele) == 0)
{
memcpy(pc->Blacklist[pc->bl].name, pc->data[i].name, sizeof(pc->data[i].name));
memcpy(pc->Blacklist[pc->bl].sex, pc->data[i].sex, sizeof(pc->data[i].sex));
memcpy(pc->Blacklist[pc->bl].tele, pc->data[i].tele, sizeof(pc->data[i].tele));
memcpy(pc->Blacklist[pc->bl].add, pc->data[i].add, sizeof(pc->data[i].add));
pc->Blacklist[pc->bl].age = pc->data[i].age;
int ret = Find(pc, tele);//得到需要删除联系人下下标,方便后续删除
for (int j = ret; j < pc->sz - 1; j++)
{
pc->data[j] = pc->data[j + 1];//从需要删除的联系人开始向后赋值,将data[i]=data[i+1],到下标为sz-1的地方
}
pc->sz--;
pc->bl++;
}
}
}
}
//打印/显示通讯录
//6.打印
void PrintContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
printf("\n1.总通讯录页面 2.特别关心页面 3.黑名单页面\n");
printf("请选择:");
int choose = 0;
scanf("%d", &choose);
switch (choose)
{
case 1:
printf("\n总通讯录页面\n");
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].add);
}
break;
case 2:
printf("\n 特别关心页面\n");
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->sp; i++)
{
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->Special_concern[i].name,
pc->Special_concern[i].sex,
pc->Special_concern[i].age,
pc->Special_concern[i].tele,
pc->Special_concern[i].add);
}
break;
case 3:
printf("\n 黑名单页面\n");
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->bl; i++)
{
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->Blacklist[i].name,
pc->Blacklist[i].sex,
pc->Blacklist[i].age,
pc->Blacklist[i].tele,
pc->Blacklist[i].add);
}
break;
default:
printf("目前还未开设其余页面!\n");
break;
}
}
//寻找人名函数
//多个函数都需要查找联系人的位置,为了方便起见,选择直接定义一个查找函数
int Find(Contact* pc, char* name)
{
assert(pc);
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;//找到返回下标
}
}
return -1;//找不到返回-1
}
//删除联系人:只需要提供姓名
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
}
printf("请输入要删除的联系人姓名:");
char name[MAX_NAME];//定义一个需要删除的联系人,后面去比对
scanf("%s", &name);
int ret = Find(pc, name);//得到需要删除联系人下下标,方便后续删除
if (ret == -1)
{
printf("没有找到要删的联系人\n");
return;
}
else
{
int i = 0;
for (i = ret; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];//从需要删除的联系人开始向后赋值,将data[i]=data[i+1],到下标为sz-1的地方
}
}
pc->sz--;//实时更改sz的大小
}
//修改通讯录的信息
void ModifyContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
}
printf("请输入要替换的联系人:");
char name[MAX_NAME];
scanf("%s", &name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("没有找到要替换的联系人\n");
return;
}
else
{
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].add);
printf("修改成功\n");
}
}
//通过人名查找信息
void Search_by_num(Contact* pc)
{
printf("请输入要查找的联系人:");
char name[MAX_NAME];
scanf("%s", &name);
int ret = Find(pc, name);
if (ret == -1)
{
printf("没有找到该联系人\n");
return;
}
else
{
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].add);
}
}
//通过号码查找信息
void Search_by_tale(Contact* pc)
{
printf("请输入联系人的号码:");
char tele[MAX_TELE];
scanf("%s", tele);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
int ret = i;
if (strcmp(pc->data[i].tele, tele) == 0)
{
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].add);
}
}
if (i == pc->sz - 1)
{
printf("未找到该联系人的信息!\n");
}
}
//通过地址来查找信息
void Search_by_add(Contact* pc)
{
printf("请输入联系人的地址:");
char add[MAX_ADD];//地址
scanf("%s", add);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
int ret = i;
if (strcmp(pc->data[i].add, add) == 0)
{
printf("%-20s\t%-10s\t%-4s\t%-20s\t%-10s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-10s\t%-4d\t%-20s\t%-10s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].add);
}
}
if (i == pc->sz - 1)
{
printf("未找到该联系人的信息!\n");
}
}
//查找联系人
void SearchContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空\n");
}
printf("请输入以什么内容来查找联系人(1.姓名/2.电话/3.地址):");
int num = 0;
scanf("%d", &num);
switch (num)
{
case 1:
Search_by_num(pc);
break;
case 2:
Search_by_tale(pc);
break;
case 3:
Search_by_add(pc);
break;
default:
printf("输入错误!\n");
break;
}
}
//自定义比较函数
int Comparestu(const void* e1, const void* e2) {
return ((struct Peoinfo*)e1)->age - ((struct Peoinfo*)e2)->age;//以年龄作为比较对象
}
//排序函数
void SortContact(Contact* pc) {
//这里的排序我们可以用qsort来实现
qsort(pc->data, pc->sz, sizeof(pc->data[0]), Comparestu);
printf("排序完毕,可使用打印查看!\n");
}
6.3,test.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void meun()//菜单
{
printf("********************************************\n");
printf("*************** 〇退出程序 ***************\n");
printf("************ ①添加联系人信息 ************\n");
printf("************ ②删除联系人信息 ************\n");
printf("************ ③查询联系人信息 ************\n");
printf("************ ④修改联系人信息 ************\n");
printf("*********** ⑤给联系人信息排序 ***********\n");
printf("************ ⑥展示联系人信息 ************\n");
printf("************* ⑦添加黑名单 ***************\n");
printf("********************************************\n");
}
void test()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
meun();
printf("\n请输入:");
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 SORT:
SortContact(&con);
break;
case PRINT:
PrintContact(&con);
break;
case ADDBlacklist:
Blacklist(&con);
break;
case EXIT:
DestroyContact(&con);
break;
default:
printf("该选项不存在!\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}