一、大型实验的内容
基本要求:能从文件读出快递派送及收件纪录信息,并能将信息保存到文件。
快递业务的信息记录包括:快递单号、快递类别(派送单/收件单)、寄送人地址、寄送人电话、寄送人备注信息、收件人地址、收件人电话、收件人备注信息、收件日期、派送日期、签收日期(是/否)、金额、是否疑难件(是/否)、疑难件备注(记录难以派送原因:地址模糊、用户拒收、电话无效、无人在家)等
功能要求:
- 设计菜单实现功能选择;
- 增加和删除快递单记录、修改快递单纪录;
- 查询派送快递单信息、收件单信息(可以根据单号、快递类别、收件日期、派送日期查询)
- 根据收件日期统计快递单数量、金额。
- 根据派送日期显示未签收的快递单、显示所有的疑难件。
- 可以将快递信息按日期、快递类别、金额等信息项进行排序显示;
- 使用文件读取相关的信息(将信息存入文件或者从信息中读取信息进行操作);
二、运行幻境
快递业务管理系统在Visual Studio 平台下开发,操作系统:Windows 10。
硬件环境:
处理器:Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz 2.11 GHz
内存:99.9GB(C)+379GB(D)
系统类型:64位操作系统
三、实验课题分析
3.1 快递业务管理系统(EMBS)的主要功能
快递业务管理系统(EMBS)主要功能为:快递管理,可以完成查询快递信息、统计快递信息、修改快递信息等功能。
详细的系统功能结构为图1所示
系统各模块的功能具体描述为:
1、登录模块
选择登录身份(游客、管理员),若为管理员,输入用户名和密码,与从文件中读取的工作人员信息相匹配,成功登录后进行相应的功能模块,若登录失败超过三次,自动退出系统。若为顾客身份,则要求输入手机,开放相关快递信息,退出登录的时候则要保存当前系统的所有状态,包括快递信息和当前所有有效人员的信息。
- 顾客模块(快递信息部分开放,只开放包含游客的部分)
根据顾客输入的电话信息,对顾客开放相关的快递信息。
2、管理员模块(快递信息全部开放)
(1)查询快递信息(不涉及信息的删改)
【1】快递信息查询:输入检索条件(包括快递单号、快递类别、收件人、寄件人、派送日期、接收日期、金额等快递属性信息),显示相关信息。
【2】快递信息排序:输入检索条件(包括快递单号、快递类别、收件人、寄件人、派送日期、接收日期、金额等快递属性信息),对快递信息进行排序。
【3】快递信息统计:输入检索条件(包括快递单号、快递类别、收件人、寄件人、派送日期、接收日期、金额等快递属性信息),对相关快递信息进行统计,输出金额、快递件数
【4】疑难件信息查询:显示所有疑难件信息。
- 修改快递信息(涉及信息的删改)
【1】增加快递:在快递信息中增加快递信息,同步更新已存在的快递信息。
【2】修改快递:修改已存在的快递信息。
【3】删除快递:删除已存在的快递信息,同步更新疑难件内容。
- 系统操作
【1】修改密码
【2】管理员注册
3.2 系统分析及设计
系统基于2个不同的身份使用系统进行功能设计,不同身份功能归纳如下表:
表1 人员类涉及的操作
身份 | 功能模块 | 具体功能 |
顾客(customer) | 查看相关快递信息 | |
管理员(manager) | 修改 | 增加快递信息 |
删除快递信息 | ||
修改快递信息 | ||
查询 | 查询快递信息 | |
快递信息排序 | ||
快递信息统计 | ||
疑难件查询 |
可以采用面向对象的方式实现快递业务管理系统(EMBS),系统涉及1个含有2个顾客(custumor)类成员、1个日期(date)结构体成员的快递(delivery)类声明的疑难件(question_delivery)类。
图2 系统主要类结构图
用文本文件进行数据的保存,需要保存的数据主要包括快递数据、管理员身份数据(包括账号、密码)。设置数据操作类,实现所有的文本操作相关的功能。
3.3系统的实现
(1)类的编写
系统工程名为:EMBS。包含了delivery类(快递类),customer类(顾客类)、date结构体(日期),question_delivery类(疑难件类)。
具体类的结构声明如下:
- 文件的直接读写
在系统的登录模块、部分功能以及意见与反馈模块,有些功能并不需要通过遍历链表来实现,而是通过对文件的直接读写来实现
- Manager-login
本系统针对不同的身份开放不同的权限,对于manger(管理员)身份,系统开放所有的快递信息,而对于custmor(顾客)身份,系统只开放部分信息和查询功能,因为权限较低,系统。而对于manager(管理员)的高权限,相应的也需要身份验证,这是本系统登录模块设计的意义。若选择其他身份,即输入非法,则执行以下语句
std::cout << "erro:enter the wrong identity!" << endl;
std::cout << "The system is ready to close!"<<endl;
然后关闭系统。
登录模块界面如图3所示
选择身份manager(管理员)后,调用函数login_scence,输入用户名和密码,在文件中读取数据并进行判断,若成功返回true值,记录登录成功,失败返回false值,失败超过3次,为保护系统,系统自动关闭;若成功,成功进入功能选择界面。
登录界面流程如下图所示:
- 快递单修改-增加
在系统界面快递单的增加界面如图4所示,只需跟着提示一步一步输入相关属性即可完成操作。
快递单的增加区别于其他功能,不会对已有的数据产生影响,只需在已有数据后面增加数据,所以不需要用到链表和其他操作,只需建立快递对象后直接对文件进行读写。
- 意见与反馈模块
在所有功能实现后,系统设置了意见与反馈模块,用户可以在该模块对系统进行打分。
意见与反馈模块如图5所示:
为了系统更好地完善,设计了意见与反馈模块。为了封装数据,这个模块的设计是单向的,系统无法读取,只能输入,而开发人员可以通过后台看到用户对系统的反馈,单向输入的特性决定了该功能模块只需要进行文件的直接读写。
(3)链表的使用
系统实现采用文件的输入输出流对文本数据进行读取与写入,但是由于快递信息是一个数据的集合,于是对数据的存储组织使用了单向链表。
因为快递业务管理系统在登录、查找、修改、添加的时候都需要处理大量的数据,所以使用链表十分必要。以快递信息为例,在delivery类的基础上定义一个对应的exel类来管理快递数据,具体的结构声明如下:
在运用时,令当前快递的next结点指向新的快递结点,即结点的指针next保存新的图书结点的地址(如下图3所示),以此类推,所有快递信息就通过链表的形式串联起来了。
快递管理系统的信息的管理就具体表现为链表的操作。快递快递信息的查找、修改、添加和删除与链表的查找、修改、添加、删除对应。
- 快递单查询-查询:
系统利用链表实现快递单的查询功能,以管理员对快递的查找为例,管理员根据快递不同属性对快递的查找有以下6种模式,管理员输入数字对应相应的模块,见图6
图6 快递查找界面
调用待查找exel对象的delivery_search的函数,先建立一个ans链表待用,从第一个exel类的第一个节点开始,会将快递对应属性和用户输入的key值比较,一致时,通过调用ans的成员函数add_delivery插入节点,以此类推,直到遍历链表,返回ans链表。再调用ans链表的成员函数display显示查找结果。
若选择模式时,输入非法模式,则执行语句,要求重新输入(下面涉及delivery_search函数与此情况相同):
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
std::cout << "erro:choose illegally!" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
std::cout << "please enter again" << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
std::cout << "请输入检索条件(1.快递单号;2.快递类型;3.寄送人/收件人 4.派送日期 5.接收日期6.金额 ):";
若未找到相关快递信息,则返回空链表,调用display函数时,若为空链表,则会执行语句(下面涉及display函数与此情况相同):
std::cout << "warn:no related info!"<<endl;
快递查找的流程图如下
- 快递单修改-删除
系统利用链表支持快递的批量删除,删除功能根据不同属性提供6种模式,输入数字选择不同模式,如图7
图7 快递删除界面
调用原exel对象的delivery_search的函数,找到待删除的链表ex,调用原exel对象的remove函数,遍历ex,循环嵌套,遍历原exel对象,通过改变next的指向,删除找到的节点,得到已经过删除处理的exel对象,再调用成员函数write对文件进行更新。
快递删除的流程如下:
- 快递单查询-统计
系统利用链表支持批量快递的数额与金额统计,统计功能根据不同快递属性,提供6种模式。见图6
图6 快递统计界面
调用原exel对象的delivery_search的函数,找到待统计的链表ex,调用ex对象的成员函数calculate,输出统计信息。
快递统计的流程如下
- 快递单修改-修改
系统利用链表支持快递单的修改功能,统计功能根据不同快递属性,提供6种模式。见图7
图7 快递修改界面
将快递单的修改分成两个部分,快递单的删除和快递单的建立,快递单的删除流程如上,再调用write_express建立一个新的快递单,再调用delivery的成员函数write_files写入文件。
快递修改的流程如下:
(4)标准库容器和算法的使用
- 快递单查询-排序
系统提供快递排序的功能,根据快递的属性,有六种排序方式,如图8所示:
图8 快递排序界面
选择模式,即排序条件后,调用cmpp函数为sort函数的参数,实现exel类型vector的排序。
- 实验调试、测试、运行记录及分析
(一)调试
系统在调试测试过程中遇到若干问题,不过经过仔细反复的检查已经消除各种bug,进行功能分支的简要试验,实际实验进行多次多种选择,以下仅截取部分
打开系统
身份选择
- 身份选择(输入1)
输入管理员身份和密码,进入功能模块选择界面
例:nickname:cry
Password:123456
1.1.1功能选择(1-1)
增加快递单,以上图信息为例
1.1.2功能选择(1-2)
1.1.3功能模块(1-3)
T
通过快递单号进行快递单删减,得到预期结果
1.2功能选择(2-1-1)
进行快递单号查询,得到预期结果
1.2.2(2-2-1)
按照快递单号对快递进行排序,得到预期结果
1.2.3功能模块(2-3)
展示疑难件信息,得到预期结果
1.2.4功能模块(2-4)
统计寄送件信息,得到预期结果
- 身份选择(输入2)
输入相关信息,得到预期结果
- 意见与反馈
- 问题
1.功能模块:manager-1-2
问题描述:该功能模块当将快递单信息由非疑难件改为疑难件时,疑难件信息未更新
解决办法:修改代码对疑难件操作。
- 功能模块:manager-2-2
问题描述:由于采用sort函数进行排序,第三个函数参数根据检索条件的不同进行排序,cmpp函数尝试用传参的方法,改变执行函数体,一直报错。
解决方法:采用全局变量取代传参的方法。
附录:源代码
完整文件可见主页资源