目录

一,项目结构分析

二,项目文件划分

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<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;
}

C语言:模块化实现通讯录相关推荐

  1. c语言通讯录打电话,C语言实现简易通讯录 | 术与道的分享

    #include #include #include #include #include #pragma warning (disable:4996) enum Contact //枚举变量 { Qu ...

  2. android运用 sqlite 实现简单的通讯录_大一新生作品:利用 C 语言实现quot;通讯录管理系统quot;,直言太简单...

    说明: 本系统基于C语言实现班级通讯录管理系统,为大一时学习C语言刚入门所做的课程设计.功能包括增.删.查.改等,非常适合初学者练手.通讯录包括的个人信息有姓名.学号.性别.籍贯.政治面貌.手机号.Q ...

  3. keil c语言模块化编程,keil C模块化编程总结

    昨晚看了下模块化编程的东西,把自己的工程整了整,可惜没成功.今早发神经似的起床敲代码,很快就发现了错误,原来是条件宏定义的头文件名忘改了,汗!!! 整理下模块化编程的要点,感谢以下三位UP主的帖子: ...

  4. c语言3级菜单_大一新生作品:利用 C 语言实现quot;通讯录管理系统quot;,直言太简单...

    说明: 本系统基于C语言实现班级通讯录管理系统,为大一时学习C语言刚入门所做的课程设计.功能包括增.删.查.改等,非常适合初学者练手.通讯录包括的个人信息有姓名.学号.性别.籍贯.政治面貌.手机号.Q ...

  5. 单片机c语言模块化实例程序设计,单片机C语言模块化设计

    原标题:单片机C语言模块化设计 keil中实现 模块化编程.doc 在使用 KEIL 的时候,我们习惯上在一个.c 的文件中把自己要写的东西按照 自己思路的顺序进行顺序书写.这样是很普遍的写法,当程序 ...

  6. C语言文件操作+通讯录实现文件操作

    文章目录 前言 一.为什么使用文件 二.什么是文件 三.文件的打开和关闭 四.文件的顺序读写 五.文件的随机读写 六.文本文件和二进制文件 七.文件读取结束的判定 八.文件缓冲区 前言 电脑文件,也可 ...

  7. C语言版动态通讯录(增、删、改、查(查重)、去重、排序、导出)

    C语言版动态通讯录(增.删.改.查(查重).去重.排序.导出) 一段学习过后,想写小东西加深下印象和理解,便开始了我的动态通讯录之旅. 整体框架及实现 通讯录主体 typedef struct con ...

  8. 用c语言设计通讯录软件下载,C语言编写的通讯录.doc

    C语言编写的通讯录.doc 1目 录一. 训练项目 2二. 训练目的 2三. 设计分析 2四. 设计方案 2五.实训 详细设计 3六. 使用说明 4七. 运行调试 4八. 训练心得 4九. 参考文献 ...

  9. C语言模块化编程样例

    模块化编程向来不是面向对象语言的专利,即使是C语言,为了降低文件.模块间的耦合度,依然要注意对变量.函数进行封装. 以下举例对C语言模块化编程进行浅析:项目中包含a.c和b.c文件,其中a.c中定义了 ...

  10. c语言手机通讯系统报告书,定稿毕业论文_C语言_手机通讯录管理系统设计最终定稿(范文1)...

    <毕业论文:C语言_手机通讯录管理系统设计.doc>由会员分享,可免费在线阅读全文,更多与<(定稿)毕业论文_C语言_手机通讯录管理系统设计(最终定稿)>相关文档资源请在帮帮文 ...

最新文章

  1. 机器学习模型部署都有哪些坑?
  2. JFinal-ext PoiRender导出Excel 列顺序混乱的问题解决办法
  3. linux系统安全设置
  4. onethink后台编辑器 提示:未检测到兼容版本的flash
  5. 语音用户界面基本设计原则
  6. 重构客户注册-基于ActiveMQ实现短信验证码生产者
  7. MapReduce V1:Job提交流程之JobTracker端分析
  8. ndarray是什么_python数据分析用什么软件?
  9. 使用 powershell 的 grep 过滤文本
  10. 【C】输出乘法口诀表
  11. UVA11173 Grey Codes【位操作】
  12. 多网卡Iptables端口转发
  13. 新句子:没有谁比我更懂XX,抓普也不行
  14. 数据预处理——matlab拟合工具箱
  15. java 文件流下载pdf
  16. 矩阵卷积运算的三种方式及C语言实现
  17. spacy词性标注解释【dep、pos、tag】
  18. 远程桌面无法连接解决方法
  19. 部署在服务器上的行驶证识别api接口
  20. 神器vimium:比同级程序员成长更快,我主要靠它

热门文章

  1. 计算机程序设计专业图片,计算机设计类软件中图片制作教学的意义论文
  2. idea提交svn忽略文件
  3. Excel 2010 VBA 入门 036 替换所有的错误值
  4. 第三方平台标识头像数据库设计参考
  5. android7 三星s7新功能,三星S7升级Android7.0在即 新增Samsung Pass功能
  6. Flutter仿抖音点击进入直播间按钮动画实现
  7. 分布式一致性协议之Raft
  8. Lifecycle详解
  9. RefreshIndicator
  10. 纪中游记 - Day 4