- 前言:这个小项目用来复习C语言,项目中的bug欢迎指出
- 一.项目需求
- 二.项目的整体结构
- 1.数据结构模块
- 联系人信息
- 通讯录
- 2.内部接口模块
- 3.外部接口模块
- 三.核心代码及思路
- 1.将通讯录中的数据写入文件
- 2.初始化通讯录
- 3.添加联系人
- 4.删除联系人
- 5.修改联系人
- 6.清空通讯录
- 7.按照姓名对通讯录中的联系人进行排序
- 四.源码
实现一个简单的通讯录,能够进行对联系人信息的添加、删除、修改、查找,并按照姓名进行排序
项目通过文件实现对数据的持久化存储
姓名、性别、年龄、职业、手机号、通讯地址
通过结构体将联系人信息组织到一起
//联系人信息
//让占用的字节数大的排列到前面,这样内存对齐时占用的内存小
typedef struct Contactor
{
char address[MAXADDRESS]; //通讯地址
char Name[MAXNAME]; //姓名
char Profession[MAXPROFESSION]; //职业
char PhoneNumber[MAXPHONENUMBER]; //手机号
enum Sex sex; //性别
int age; //年龄
}Contactor;
通讯录
通讯录中由多个联系人组成,所以通讯录中不仅要有一个动态的联系人数组,还要有一个当前联系人个数,为了方便后面判断通讯录是否已满进而重新为联系人开辟空间,还要有一个通讯录容量
//通讯录
typedef struct MailList
{
Contactor* list; //联系人信息
int count; //当前数据条数
int capactiy; //通讯录容量
}MailList;
2.内部接口模块
内部接口只允许在本源文件中使用,不允许外部调用,用static进行修饰
这些接口都是为了完成对外提供的接口而定义的辅助接口,不需要暴露给外界
接口有:
对通讯录的增容
将联系人信息从文件读取到通讯录
将通讯录信息写入文件
判断通讯录中是否存在某位联系人
对外提供一些接口,用来实现通讯录的功能
接口有:
销毁通讯录
初始化通讯录
添加联系人
删除联系人
修改联系人
查找联系人
按照姓名对联系人进行排序
显示所有联系人
清空通讯录
遍历通讯录中的联系人信息,每次将一个联系人信息写入通讯录,这个接口因为要用于不同的场景,所以要有一个打开方式选项mode
接口如下:
//将数据从通讯录写入文件 //mode是写入的模式 static void WriteDataFromContactor(MailList* mlst, const char* mode);2.初始化通讯录
1)为通讯录中的联系人数组申请堆上的空间、指定容量和设置当前元素个数为0
2)把文件中的数据加载到到通讯录中
//初始化通讯录 void InitMailList(MailList* mlst);3.添加联系人
1)将联系人信息保存到一个Contactor结构体变量中;
2)将联系人信息保存到通讯录中;
3)将通讯录数据覆盖写入文件(注意是将原文件中的数据进行全部替换)
//添加联系人 void AddContacter(MailList* mlst);4.删除联系人
1)根据姓名找到联系人在通讯录中的位置;
2)从找到的位置开始所有数据往前移动一个位置;
3)更新通讯录元素个数;
4)将通讯录数覆盖写入文件;
//删除联系人 void DeleteContacter(MailList* mlst);5.修改联系人
1)根据姓名找到联系人在通讯录中的位置;
2)重新编辑联系人信息;
3)将修改后的通讯录数据覆盖写入文件;
//修改联系人信息 void ModifyContacter(MailList* mlst);6.清空通讯录
1)将通讯录中存储的联系人信息全部清空,并还原为初始化状态;
2)删除存储通讯录数据的文件;
//清空通讯录 void ClearMailList(MailList* mlst);7.按照姓名对通讯录中的联系人进行排序
自定义比较函数,通过调用qsort这个快速排序接口来对通讯录数据进行排序
//按照姓名对所有联系人排序 void SortContacterByName(MailList* mlst);
自定义比较函数如下:
//按照姓名首字母从小到大排序
int CompareByName(const void* a, const void* b)
{
Contactor* str = (Contactor*)a;
Contactor* str2 = (Contactor*)b;
return strcmp(str->Name, str2->Name) > 0;
}
四.源码
Contactor



