目录
一,项目结构分析
我用思维导图的方式来展示我编写的通讯录所具有的功能:
二,项目文件划分
2.1 头文件(contact.h)
#pragma once
//库函数
#include<stdio.h>
#include <assert.h>
#include<string.h>
#include <stdlib.h>
//宏定义,方便后期修改数值时不用依次修改
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 20
#define MAX_ADD 10
#define DEFAUT_SZ 3;//初始化通讯录的容量为3人
/// <summary>
///可以储存1000个联系人信息的
/// </summary>
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<stdio.h>
#include <assert.h>
#include<string.h>
#include <stdlib.h>
//宏定义,方便后期修改数值时不用依次修改
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 20
#define MAX_ADD 10
#define DEFAUT_SZ 3;//初始化通讯录的容量为3人
/// <summary>
///可以储存多个联系人信息:即在初始化3人的基础上满则加
/// </summary>
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;
}