♻️ 资源
大小: 2.83MB
➡️ 资源下载: https://download.csdn.net/download/s1t16/87472196
https://download.csdn.net/download/s1t16/87472196
个人通讯录管理系统
代码实现语言 cpp,可视化框架使用 MFC
一、选题背景
本课题应能实现个人对通讯录的基本管理,应达到的技术要求及功能如下:
(1)提供录入个人信息、修改个人信息(姓名和出生日期除外)、删除个人信息等编辑功能
(2)提供按姓名查询个人信息的功能
(3)提供查找在 5 天之内过生日的人员的信息,以便发出祝贺电话或 E_mai
(4)按照姓名或出生日期排序,显示输出
(5)统计在给定月份出生的人数,并显示输出
(6)能列出全体人员的姓名、出生日期、电话和 email 地址
(7)能分别列出同学、同事、朋友、亲戚的所有信息
(8)用菜单形式提供程序的各种功能的选择
整个应用程序设计的指导思想主要是基于类对数据进行管理和通过调用函数实现对数据的操作,最后通过前端可视化调用进行展示。
二、方案论证
设计思路:
基于类对数据进行管理
通过调用函数实现对数据的操作
最后通过在前端窗口类设置类成员实现对数据的管理展示,将操作触发与相关函数联系实现对数据的操作
这里只分析应用后端处理数据的类,可视化部分直接用了对话框形式,在结合控件的处理函数基础上实现各个功能,背后实际上调用的是后端设计好的函数及相关类。。
应用主要定义了三个类:ListSystem,HashList,Node;
两个结构:OneRecord,MoreInfo;
除此还有多个可视化窗口类,如下是整体架构设计思路:

(1)OneRecord:主要是存储个人通讯录中的一个联系人的信息集合,包含了姓名、出生日期、手机号、邮箱、分类标签(同学、同事、朋友、亲戚)、其他根据各个标签的补充,像同学则为一起就读的学校信息。

图 1 OneRecord 结构
(2)MoreInfo:这个结构主要是 OneRecord 结构信息的补充,用于后面统计五天以内过生日的所有联系人信息,能够更好展示更多信息,里面包含了 OneRecord 成员,联系人最近生日的星期,以及一个序号,用于排序,将联系人按照生日从前到后排序。

图 2 MoreInfo 结构
(3)Node:这个类的定义主要是用于 HashList 哈希链表中,包含了 OneRecord 成员,以及指向下一个的 next 指针。

图 3 Node 结构
(4)HashList:这个类主要实现开放式哈希链表的功能,用姓名首字母作为标准分为 26 部分,主要实现应用中的快速查询功能,以及查询中的子串匹配功能,这里是因为考虑到主类 ListSystem 中用了四个容器去分别存储对应标签的联系人,在查询上效率低,而哈希表里面包含到了所有联系人的信息,同时因其所有的特殊功能能够实现快速查询功能。

图 4 HashList 类结构
(5)ListSystem:这个是这个应用的主要类,继承了 HashList,所以它能够拥有哈希表的快速查询功能,在使用时只需调用在哈希表中定义的函数即可;而这个类本身定义了四个 vector容器用于存储对应的四个分类标签的联系人,也正好对应了储存信息的四个文件,后续所有对于实现联系人的增加、删除、修改以及统计功能等的函数都定义在这个类中。

图 5 ListSystem 类结构
三、过程论述
整个应用的设计实现过程主要是先实现一个整体框架,包括对数据的存放单位,数据中各个属性的类型定义等,也就是上图中的各种类定义;
然后按照功能模块分开实现,根据需要在类中定义相关操作函数,直接对类数据成员即通讯录的人员进行操作;
最后在可视化中将定义好的菜单控件与相关函数联系起来实现在可视化中操作数据。
下图是整个应用设计实现的简单流程图:

图 6 应用设计流程图
下面根据各个功能划分对类函数的实现进行说明(具体实现参考源代码):
(1)按姓名排序:
这个功能的实现主要由主类中的 SortName(int index)函数实现,参数为同学、同事等容器的索引,这个函数主要调用另一个定义的函数 QuickSort(int index, int low, int high)实现,在这个快排中,第一个参数为同学、同事等容器的索引,另两个分别为需要排序的数组的前后下标,主要是利用递归算法,主要思想是分而治之,通过前后索引向中间靠拢,将小于预定值的数调换到左边,大于换到右边,找到预定值所处的下标位置,这个位置就是排序了数组中预定值的位置,然后在分别对预定值两边的数组进行同样的操作,即改变相应的实参 low 与 high 调用 QuickSort 函数。直到左右两边都没有数停止调用,这时就已经排好序,时间代价为

。
(2)应用初始化:
初始化主要有两个函数 ListSystem() 与 HashList(),分别为主类和哈希表的构造函数,当程序运行时,首先在 ListSystem()中按照 4 个文件与数据成员中 4 个 vector 容器一一对应关系,将文件中的联系人信息全部加载到对应容器中,然后调用定义好的 SortName(int index)函数将容器的数据按姓名排序,同时在 HashList()中也将其插入到哈希表中,同步实现,以供后面调用,在插入时会找到对应的位置插入,也保证了哈希表是按姓名排序的,这样在后面展示所有数据时直接调用哈希表显示就成。
(3)录入个人信息:
录入个人信息实际上就是将录入的信息插入到数据成员 vector 中,这里定义了 booInsert(OneRecord v, int t),一参为信息,二参为容器下标,实现主要是从头开始遍历,插入到按姓名排序它所在的位置,然后后面值往后移,成功则返回 true,如果有相同姓名的则插入失败,时间代价为

;在哈希表中同步定义了 protected 限制的 InsertNode(Node n),由前者调用,实现主要是根据首字母定位到相应链表中,然后遍历找到位置,申请新的空间存放它,修改前后指向指针保证整个链表一致,时间代价最好时为常数。
(4)删除个人信息等编辑功能:
删除个人信息由函数 void Delete(string s, int t)实现,一参为其姓名,二参为容器索引,在对应容器中从头遍历找到该姓名,然后开始将后面信息往前覆盖,最后把容器最后一个多余的信息 pop_back 掉,时间代价为

;在哈希表中同步定义了 protected 限制的 void DeleteNode(string s),由前者调用,同插入相似,从头遍历,找到姓名对应的节点,修改前后指针指向,保证链表一致,再将该节点释放。
(5)修改个人信息(姓名和出生日期除外):
修改个人信息由于可能会涉及到分组的修改,例如从朋友改为同学,则对应该信息存放容器也会改变,所以这里用了先删除原始信息,再将修改后的信息插入进去,实现修改功能。
(6)提供按姓名查询个人信息的功能:
查询功能主要是在哈希表中实现,一来是因为哈希表包含所有数据,而在 ListSystem 类中,数据是按照不同分组分别放置在不同的容器中,不利于查询,在哈希表中查询由函数 booFindInName(string s, OneRecord& result)实现,一参为姓名,根据姓名首字母找链表入口再从头开始遍历,找到对应信息后赋值给二参引用返回。在查询的实现上,我这里扩展了下,实现子串匹配搜索,就是当用户在输入框输入姓名时,可以根据他的输入将符合的姓名全部以下拉框的形式给出供其选择,对应函数为哈希表中的 int FindSubName(string s, vector& vec_s),同上述查询相似,逐个遍历,包含子串的姓名都放置于引用容器中返回,返回值为个数。
(7)提供查找在 5 天之内过生日的人员的信息,以便发出祝贺电话或 E_mail:
这个功能的实现主要由 void BirthInFive(vector& vec,int& monthdata,string& w_str)函数实现,其中一参传 5 日内的联系人信息,二参传今天日期(整型),三参传今天的星期。查找 5 天内的联系人主要由 <time.h> 库中的 mktime 实现,将今天的日期和五天后的日期转换为整型,如 10 月 8 日转成 1008,这个从日期到数值的转换由函数 GetBirthdataInt(string s)实现,根据日期 xxxx.xx.xx 特点,以"."为分隔找到对应日期并从字符串转成数字,按一定乘法后相加并返回。
然后分两种情况,一种是 5 日不跨年的,遍历所有人的信息,根据他们的生日整型是否为于前面提前得到的两个整数之间,是则在 5 天之内过生日,对应的星期根据生日整数之间的差值,由当天星期相加得来。另一种就是 5 日内刚好跨年的,判断条件就改为在两个整数两边,即小最小那个或者大于最大的那个都是在 5 日之内过生日的。将信息放置在引用容器中返回。
void MakeText(string name)这个函数根据确定的姓名生成祝贺文本,主要是修改了文本中的姓名为可变的参数 name,其他按照对应格式输出到文本中即可实现。
(8)统计在给定月份出生的人数,并显示输出:
这个功能主要是基于主类中的 count_month 数据成员,在初始化时、插入、修改等时同步更新统计各个月份的人数,可视化时直接按照月份找到对应下标输出即可。
(9)保存信息到文件中:
SaveList()函数以 Ios::out 的格式打开每个文件,然后将与文件对应的容器中的信息从头开始遍历写入,每个联系人信息占据一行,相同人不同信息在同一行中以空格进行分隔,直到全部写入关闭文件。
(10)能列出全体人员的姓名、出生日期、电话和 email 地址,能分别列出同学、同事、朋友、亲戚的所有信息:
这个主要在可视化中实现,根据对应选择,如果是所有人,则将哈希表中的信息遍历显示出,如果选择的是同学、朋友等,则根据其在主类 ListSystem 中选择对应的容器,遍历输出该容器里面的所有信息即为你选择的分组的所有信息。
(11)用菜单形式提供程序的各种功能的选择:
整个应用主要用了 MFC 可视化,各种功能也是以菜单形式提供选择,例如增加联系人,则定义了增加按钮控件,在这个按钮的点击响应函数中定义了一个额外的对话框给用户输入需要增加的联系人信息,确定后,对信息进行捕获并调用前面定义好的插入函数,将联系人插入到类容器中。同时更新界面的数据显示。其他功能菜单实现相似。
四、结果分析
1、登录界面功能,用户名和密码都是预先设定的,按登录按钮密码用户名正确跳转到主页面,否则提示错误。

图 7 登录界面
2、
下面为应用主界面,首先下拉框可以选择要显示的分组:所有、同学、同事等;菜单栏中包含了功能选择;列表显示数据;查询功能放在页面之上,方便快捷。

图 8 应用主界面展示
3、
录入功能的实现,在编辑中找到录入点击进去,填写信息,确定,则会自动将数据插入到容器中,同步更新到后端数据,如下:

图 9 录入功能
4、删除功能的实现,首先选择要删除的数据,然后在点击删除,可以大量删除,如果没选的话就点击,会有相应的提示。

图 10 删除功能展示
5、
修改功能的展示,这里除了选中数据,再点击菜单里提供的修改按钮,也可以直接双击要修改的数据,直接快捷进入修改页面,在修改页面中按要求限制了姓名和生日不可修改,修改页面增加了删除按钮,可以实现删除功能。

图 11 修改功能展示
6、根据下拉框的选择列表呈现不一样的数据,主要是调用显示的容器不一样,如下为执行结果:

图 12 数据分组显示功能展示
7、五日内过生日的联系人信息查找功能主要是调用函数返回数据给前端在显示出来,如下执行结果:

图 13 5 日内过生日联系人查找功能展示
8、统计给定月份出生人数功能主要是以下拉框形式提供月份选择并返回对应的月份的人数以静态文本显示,如下为执行结果:

图 14 统计月份出生人数功能展示
9、查询功能实现按姓名查找,扩展实现了子串匹配查找,以下拉框展示结果提供选择,方便快速查询,查询成功则展示该联系人的修改编辑对话框,否则提示不存在该联系人,如下执行结果:

图 15 查询功能展示