地铁收费管理系统
考试提醒
● 请仔细阅读规格文档,理解规格文档估计需要花费10~30分钟来理解,请务必看清
楚要求再动手,试题包括规格描述和代码框架。
● C/C++编译环境统一为Visual C++ 6.0版本。如果你喜欢并熟悉Source
Insight 或其它工具,也可以使用Source Insight 或其它工具进行开发,但考生必须保证提交的代码要在指定编译环境下编译通过,否则无法阅卷。 ● 如果考题与日常工作/生活接近,请考生以规格为准,不要类比相似案例。
● 出于自动化测试的需要,程序中不要使用原始的I/O输入输出(键盘输入、屏幕输
出) 作为正式输入输出,我们会提供基于Socket 的输入输出API 接口,考生必须使用Socket API进行正式输入输出操作。调试输出的方式不受此限制。
● 考试的工程已经提供Socket 通信功能,并提供输入/输出的API ,考生不需要实
现。
1 总体说明
考生需要模拟实现一个简单的地铁收费系统,实现地铁交通卡或单程票的扣费、余额提示、日志记录和日志查询等功能。
1.1相邻站点间里程表
系统预置有一张“相邻站点间里程表”,作为计算基本票价的依据。其结构和内容如下:
备注:
✓ 只考虑1条地铁线路,站点关系示意:站点---站点---站点---。。。。。。---站点
---站点,无分叉,无环路,任何2站点之间的路径是唯一的,不存在多条路径的情况。
✓ 该线路上地铁双向运行。乘客可以从任何站点进站,也可以从任何站点出站。 ✓ 表中无重复记录,一对相邻站点在表中只存在一条记录,比如:S2与S4之间的
记录只有:S2->S4或S4->S2其中的任意1条,而不会同时存在2条。 ✓ 考生可以直接使用考试系统提供的根据该表计算任意2站点间最短里程的接口(接
口参见3.4 API说明)。
1.2 地铁收费系统规则
1、票价分为基本票价和扣费票价。扣费票价是在基本票价的基础上,根据票卡类型、时间段进行特殊计算得到的(也有可能等于基本票价),是扣费操作时需要从卡上扣除的金额。
2、基本票价计算规则:按进站点与出站点之间的最短里程分级计算: ✓ 3千米(包含3千米,但不包括0)以内:2元。 ✓ 3千米 至 5千米(包含5千米):3元。 ✓ 5千米 至 10千米(包含10千米):4元。 ✓ 10千米以上:5元。 struct distcost {
Char s1[]; Char s2[]; Int distance; };
3、进出站为同一站点的,则按进出站时长计算: (1)小于等于30分钟:
单程票:票卡面值作为扣费票价;
其他卡:0元,且不受任何时间段的限制,即直接作为扣费票价。 (2)大于30分钟: 单程票:(票卡面值,3元)中“最大值”作为扣费票价;
其他卡:3元,且不享受任何时间段的优惠,即直接作为扣费票价。
4、扣费票价计算规则1:按照各种票卡的类型计算: ✓ 普通卡(C ):正常时间段以基本票价作为扣费票价;特殊时间段收费参见“5、扣
费票价计算规则2”。 ✓ 老年卡(B ):正常时间段以基本票价的9折作为扣费票价(如出现小数,则向下
取整);特殊时间段收费参见“5、扣费票价计算规则2”。 ✓ 单程票(A ):即一次性车票,任何时间段不享受任何优惠,直接以(票卡面值,
基本票价)中“最大值”作为扣费票价。
5、扣费票价计算规则2(不涉及单程票):按照进站时间的不同区间计算: ✓ 进站时间为[7:00,9:00)、[16:30,18:30)时,无任何优惠,所有类型的交通
卡(单程票除外)以基本票价作为扣费票价。 ✓ 进站时间为[10:00,11:00)、[15:00,16:00)时,所有类型的交通卡(单程票
除外)以基本票价的5折作为扣费票价(如出现小数,则向下取整)。
1.3 约束
✓ 考生严格按操作说明的功能项实现,不用考虑其他异常(比如:单参数的合法性,
不同操作之间的逻辑关联性,等等)。
✓ 系统不考虑跨天的情况,只需要考虑同一天,即00:00~23:59地铁全天运行时
间范围内的功能。
✓ 所用的命令字和卡类型参数中的字母不区分大小写;站名中若出现小写字母,考试
框架自动将其转换成大写字母。
2 操作说明
采用在考试系统提供的SocketTool 工具中输入命令串方式与系统进行操作交互,命令字是该命令串的第一个符号。命令行的格式:命令字[空格]参数1...[空格]参数n
命令字与第一个参数之间、参数与参数之间,均使用英文半角空格分隔,单个参数内无空格。
2.1初始化
命令格式:r
功能说明:程序复位,使程序恢复到刚启动时的初始化状态。全局变量、链表及输出消费记录的文件等统一恢复到初始状态。
约束说明:系统在任何状态下可以执行该命令初始化系统。
输出说明:输出操作结果提示(执行完r 命令后系统会自动输出操作结果,考生不需
2.2 请求扣费
命令格式:c 卡号 卡类型 卡扣费前余额 进站时间 进站站点名称 出站时间 出站站点名称
功能说明:
1、按照输入条件和“1.2地铁收费系统规则”,对票卡进行扣费操作(减去扣费票价)。 2、输出信息调用系统已提供的接口完成(接口参见“3.4 API说明”)。
4、如果从进站点到出站点之间的路线不存在,则不扣费,输出无效路线,并显示“卡扣费后余额”(“卡扣费后余额”等于“卡扣费前余额”)。
5、如果“卡扣费前余额”大于等于扣费票价,则扣费,输出扣费成功,并显示“卡扣费后余额”。
注意:如果单程票面值大于等于扣费票价,则按票面值扣费。例如:单程票面值5元,
6、不是单程票的,扣费成功后,如果“卡扣费后余额”小于20元,则输出余额过低,并显示“卡扣费后余额”。
7、如票“卡扣费前余额”不足以扣费,则不扣费,输出扣费失败(余额不足),并显示“卡扣费后余额”(“卡扣费后余额”等于“卡扣费前余额”)。
8、调用系统已提供的写日志接口(接口参见“3.4 API说明”),将“地铁乘车记录”
记录到内存日志中,日志记录中包含如下字段:
Struct loginfo{
Int card; Long inTime; Char s1[]; Long outTime; Char s2[]; Int cost; Bool isCost; };
注意:
✓ 请求扣费操作(c/C)所有(无论是否成功或失败)输出返回时,均要求要记录日志。
(如果卡号已注销的话,不写日志)
✓ 仅请求扣费操作(c/C)才记录日志,其他任何操作(查询扣费日志(q/Q)、初始化
(r/R))均要求不要记录日志。
✓ 系统最多记录10条日志,超过的系统会自动丢弃,程序初始化(或复位(r/R))
后日志记录自动清空,自动从头记录。 约束说明:无。
输出说明:输出操作结果,统一参见“3.3 基本用例”。
2.3 查询扣费日志(本功能作为附加功能, 学员选做, 请在完成其他功能后再做)
命令格式:q 卡号 查询起始时间 查询终止时间 功能说明:
1、 查询指定票卡出站时间在指定时间段内(查询起始时间
时间)的“地铁乘车记录”日志。 备注:对于内存日志的访问,请使用系统已提供的访问日志的接口(接口参见“3.4 API
说明”)。
2、 输出日志查询结果信息,请调用系统已提供的接口完成(接口参见“3.4 API 说明”)。 4、 如果卡号为0,则查询所有票卡出站时间在指定时间段内的地铁乘车记录;
5、 查询结果按照“卡号”从小到大的顺序输出,同一卡号按照记录日志的先后顺序输
输出说明:满足条件的日志记录。
2.4 查询扣费历史记录
命令格式:h 卡号 功能说明:
1、 查询指定票卡的消费记录(只查询消费成功的记录)。 2、 如果卡号为0,则查询所有票卡的消费记录; 3、 查询结果按照消费的顺序输出。
地铁收费系统_0级
内部公开
说明:由于卡号为3的记录没有消费成功,因此只输出了卡号为4的记录。
4、 对于查询所有票卡的消费记录情况,如果没有任何记录,则输出查询失败(无相应
记录)。
5、 对于查询单个票卡的消费记录,如果没有查到满足条件的记录时,区分处理:
1)在没有任何其他票卡的消费记录存在时,输出查询失败(无相应记录)。 2)在有其他票卡的消费记录存在时,首先判断正查询的该单个票卡的有效性(是否为注销卡)。如果为注销卡,输出操作失败(此票卡已经注销)。不为注销卡,才输出说明:对于输出查询成功的情况,所有记录除了正常输出以外,同时要按照如下格式,支持查询结果存储到文件中,文件路径和本程序文件同级,文件名为:SubwayCharge.txt 。 输出格式:
卡号:* 卡类别:* 进站时间:*:* 进站名称:* 出站时间:*:* 出站名称:* 费用:*
举例:
卡号4,卡类别:老年卡,进站时间:10:05,进站名称:S1,出站时间:11:20,出站名称:S4,费用:2,则输出格式为:
卡号:4卡类别:老年卡 进站时间:10:05 进站名称:S1 出站时间:11:20 出站名称:S4 费用:2
写文件时,每个字段后用英文半角空格分隔分开。输出到文件时需要遵从上面功能说明的第2、3条约束。
SubwayCharge.txt 以覆盖方式写入,系统初始化时清空. (写日志文件作为附加功能, 学员选做, 请在完成其他功能后再做)
2.5 注销票卡(本功能作为附加功能, 学员选做, 请在完成其他功能后再做)
命令格式:d 卡号
功能说明:
1、 注销指定票卡的消费记录,输出:
I22:票卡注销成功
2、 如果卡号为0,则注销所有票卡,输出:
I22:票卡注销成功 3、
4、 注销后的票卡不能再进行请求扣费、扣费日志查询及再次注销操作,如有操作,输
出:E22:操作失败,此票卡已经注销;
5、 注销时,关于此票卡的历史消费信息(扣费历史记录,扣费记录)需要删除(不需
要删除SubwayCharge.txt 中的记录)。注销后的票卡需要在系统重新初始化后才能再次使用。
3 附录:
3.1 命令汇总
3.2 返回码汇总
3.3 基本用例
3.4 API说明
1、VC 工程SubwayCharge.rar 中包括:
● \lib\SocketApi.lib:是一个LIB 库文件,其中实现了对外通信接口,
考生不涉及使用,考试系统使用,不能删除;
● \lib\SubwayChargeApi.lib:是一个LIB 库文件,其中实现了对命令
输入和操作输出等公共功能的一些封装;
● \lib\ExamApi.lib:是一个LIB 库文件,其中实现了对自动化阅卷功能
的一些封装;
● \src\api.h:头文件,定义了考生可能用到的的宏、枚举、结构、函数声
明;
● \src\SubwayCharge.h:头文件,定义了考生可能用到的的宏、枚举、
结构,以及需要考生实现的接口函数声明。考生可以向其中添加自己的定义。具体要求请看函数注释。
● \src\SubwayCharge.cpp:源码文件,提供了需要考生实现的接口函数
框架,这些函数是空白的,需要由考生实现。 ● 其他文件是VC 工程自行产生的,考生不必关注。
更详细的定义请参阅VC 工程。
地铁收费管理系统
考试提醒
● 请仔细阅读规格文档,理解规格文档估计需要花费10~30分钟来理解,请务必看清
楚要求再动手,试题包括规格描述和代码框架。
● C/C++编译环境统一为Visual C++ 6.0版本。如果你喜欢并熟悉Source
Insight 或其它工具,也可以使用Source Insight 或其它工具进行开发,但考生必须保证提交的代码要在指定编译环境下编译通过,否则无法阅卷。 ● 如果考题与日常工作/生活接近,请考生以规格为准,不要类比相似案例。
● 出于自动化测试的需要,程序中不要使用原始的I/O输入输出(键盘输入、屏幕输
出) 作为正式输入输出,我们会提供基于Socket 的输入输出API 接口,考生必须使用Socket API进行正式输入输出操作。调试输出的方式不受此限制。
● 考试的工程已经提供Socket 通信功能,并提供输入/输出的API ,考生不需要实
现。
1 总体说明
考生需要模拟实现一个简单的地铁收费系统,实现地铁交通卡或单程票的扣费、余额提示、日志记录和日志查询等功能。
1.1相邻站点间里程表
系统预置有一张“相邻站点间里程表”,作为计算基本票价的依据。其结构和内容如下:
备注:
✓ 只考虑1条地铁线路,站点关系示意:站点---站点---站点---。。。。。。---站点
---站点,无分叉,无环路,任何2站点之间的路径是唯一的,不存在多条路径的情况。
✓ 该线路上地铁双向运行。乘客可以从任何站点进站,也可以从任何站点出站。 ✓ 表中无重复记录,一对相邻站点在表中只存在一条记录,比如:S2与S4之间的
记录只有:S2->S4或S4->S2其中的任意1条,而不会同时存在2条。 ✓ 考生可以直接使用考试系统提供的根据该表计算任意2站点间最短里程的接口(接
口参见3.4 API说明)。
1.2 地铁收费系统规则
1、票价分为基本票价和扣费票价。扣费票价是在基本票价的基础上,根据票卡类型、时间段进行特殊计算得到的(也有可能等于基本票价),是扣费操作时需要从卡上扣除的金额。
2、基本票价计算规则:按进站点与出站点之间的最短里程分级计算: ✓ 3千米(包含3千米,但不包括0)以内:2元。 ✓ 3千米 至 5千米(包含5千米):3元。 ✓ 5千米 至 10千米(包含10千米):4元。 ✓ 10千米以上:5元。 struct distcost {
Char s1[]; Char s2[]; Int distance; };
3、进出站为同一站点的,则按进出站时长计算: (1)小于等于30分钟:
单程票:票卡面值作为扣费票价;
其他卡:0元,且不受任何时间段的限制,即直接作为扣费票价。 (2)大于30分钟: 单程票:(票卡面值,3元)中“最大值”作为扣费票价;
其他卡:3元,且不享受任何时间段的优惠,即直接作为扣费票价。
4、扣费票价计算规则1:按照各种票卡的类型计算: ✓ 普通卡(C ):正常时间段以基本票价作为扣费票价;特殊时间段收费参见“5、扣
费票价计算规则2”。 ✓ 老年卡(B ):正常时间段以基本票价的9折作为扣费票价(如出现小数,则向下
取整);特殊时间段收费参见“5、扣费票价计算规则2”。 ✓ 单程票(A ):即一次性车票,任何时间段不享受任何优惠,直接以(票卡面值,
基本票价)中“最大值”作为扣费票价。
5、扣费票价计算规则2(不涉及单程票):按照进站时间的不同区间计算: ✓ 进站时间为[7:00,9:00)、[16:30,18:30)时,无任何优惠,所有类型的交通
卡(单程票除外)以基本票价作为扣费票价。 ✓ 进站时间为[10:00,11:00)、[15:00,16:00)时,所有类型的交通卡(单程票
除外)以基本票价的5折作为扣费票价(如出现小数,则向下取整)。
1.3 约束
✓ 考生严格按操作说明的功能项实现,不用考虑其他异常(比如:单参数的合法性,
不同操作之间的逻辑关联性,等等)。
✓ 系统不考虑跨天的情况,只需要考虑同一天,即00:00~23:59地铁全天运行时
间范围内的功能。
✓ 所用的命令字和卡类型参数中的字母不区分大小写;站名中若出现小写字母,考试
框架自动将其转换成大写字母。
2 操作说明
采用在考试系统提供的SocketTool 工具中输入命令串方式与系统进行操作交互,命令字是该命令串的第一个符号。命令行的格式:命令字[空格]参数1...[空格]参数n
命令字与第一个参数之间、参数与参数之间,均使用英文半角空格分隔,单个参数内无空格。
2.1初始化
命令格式:r
功能说明:程序复位,使程序恢复到刚启动时的初始化状态。全局变量、链表及输出消费记录的文件等统一恢复到初始状态。
约束说明:系统在任何状态下可以执行该命令初始化系统。
输出说明:输出操作结果提示(执行完r 命令后系统会自动输出操作结果,考生不需
2.2 请求扣费
命令格式:c 卡号 卡类型 卡扣费前余额 进站时间 进站站点名称 出站时间 出站站点名称
功能说明:
1、按照输入条件和“1.2地铁收费系统规则”,对票卡进行扣费操作(减去扣费票价)。 2、输出信息调用系统已提供的接口完成(接口参见“3.4 API说明”)。
4、如果从进站点到出站点之间的路线不存在,则不扣费,输出无效路线,并显示“卡扣费后余额”(“卡扣费后余额”等于“卡扣费前余额”)。
5、如果“卡扣费前余额”大于等于扣费票价,则扣费,输出扣费成功,并显示“卡扣费后余额”。
注意:如果单程票面值大于等于扣费票价,则按票面值扣费。例如:单程票面值5元,
6、不是单程票的,扣费成功后,如果“卡扣费后余额”小于20元,则输出余额过低,并显示“卡扣费后余额”。
7、如票“卡扣费前余额”不足以扣费,则不扣费,输出扣费失败(余额不足),并显示“卡扣费后余额”(“卡扣费后余额”等于“卡扣费前余额”)。
8、调用系统已提供的写日志接口(接口参见“3.4 API说明”),将“地铁乘车记录”
记录到内存日志中,日志记录中包含如下字段:
Struct loginfo{
Int card; Long inTime; Char s1[]; Long outTime; Char s2[]; Int cost; Bool isCost; };
注意:
✓ 请求扣费操作(c/C)所有(无论是否成功或失败)输出返回时,均要求要记录日志。
(如果卡号已注销的话,不写日志)
✓ 仅请求扣费操作(c/C)才记录日志,其他任何操作(查询扣费日志(q/Q)、初始化
(r/R))均要求不要记录日志。
✓ 系统最多记录10条日志,超过的系统会自动丢弃,程序初始化(或复位(r/R))
后日志记录自动清空,自动从头记录。 约束说明:无。
输出说明:输出操作结果,统一参见“3.3 基本用例”。
2.3 查询扣费日志(本功能作为附加功能, 学员选做, 请在完成其他功能后再做)
命令格式:q 卡号 查询起始时间 查询终止时间 功能说明:
1、 查询指定票卡出站时间在指定时间段内(查询起始时间
时间)的“地铁乘车记录”日志。 备注:对于内存日志的访问,请使用系统已提供的访问日志的接口(接口参见“3.4 API
说明”)。
2、 输出日志查询结果信息,请调用系统已提供的接口完成(接口参见“3.4 API 说明”)。 4、 如果卡号为0,则查询所有票卡出站时间在指定时间段内的地铁乘车记录;
5、 查询结果按照“卡号”从小到大的顺序输出,同一卡号按照记录日志的先后顺序输
输出说明:满足条件的日志记录。
2.4 查询扣费历史记录
命令格式:h 卡号 功能说明:
1、 查询指定票卡的消费记录(只查询消费成功的记录)。 2、 如果卡号为0,则查询所有票卡的消费记录; 3、 查询结果按照消费的顺序输出。
地铁收费系统_0级
内部公开
说明:由于卡号为3的记录没有消费成功,因此只输出了卡号为4的记录。
4、 对于查询所有票卡的消费记录情况,如果没有任何记录,则输出查询失败(无相应
记录)。
5、 对于查询单个票卡的消费记录,如果没有查到满足条件的记录时,区分处理:
1)在没有任何其他票卡的消费记录存在时,输出查询失败(无相应记录)。 2)在有其他票卡的消费记录存在时,首先判断正查询的该单个票卡的有效性(是否为注销卡)。如果为注销卡,输出操作失败(此票卡已经注销)。不为注销卡,才输出说明:对于输出查询成功的情况,所有记录除了正常输出以外,同时要按照如下格式,支持查询结果存储到文件中,文件路径和本程序文件同级,文件名为:SubwayCharge.txt 。 输出格式:
卡号:* 卡类别:* 进站时间:*:* 进站名称:* 出站时间:*:* 出站名称:* 费用:*
举例:
卡号4,卡类别:老年卡,进站时间:10:05,进站名称:S1,出站时间:11:20,出站名称:S4,费用:2,则输出格式为:
卡号:4卡类别:老年卡 进站时间:10:05 进站名称:S1 出站时间:11:20 出站名称:S4 费用:2
写文件时,每个字段后用英文半角空格分隔分开。输出到文件时需要遵从上面功能说明的第2、3条约束。
SubwayCharge.txt 以覆盖方式写入,系统初始化时清空. (写日志文件作为附加功能, 学员选做, 请在完成其他功能后再做)
2.5 注销票卡(本功能作为附加功能, 学员选做, 请在完成其他功能后再做)
命令格式:d 卡号
功能说明:
1、 注销指定票卡的消费记录,输出:
I22:票卡注销成功
2、 如果卡号为0,则注销所有票卡,输出:
I22:票卡注销成功 3、
4、 注销后的票卡不能再进行请求扣费、扣费日志查询及再次注销操作,如有操作,输
出:E22:操作失败,此票卡已经注销;
5、 注销时,关于此票卡的历史消费信息(扣费历史记录,扣费记录)需要删除(不需
要删除SubwayCharge.txt 中的记录)。注销后的票卡需要在系统重新初始化后才能再次使用。
3 附录:
3.1 命令汇总
3.2 返回码汇总
3.3 基本用例
3.4 API说明
1、VC 工程SubwayCharge.rar 中包括:
● \lib\SocketApi.lib:是一个LIB 库文件,其中实现了对外通信接口,
考生不涉及使用,考试系统使用,不能删除;
● \lib\SubwayChargeApi.lib:是一个LIB 库文件,其中实现了对命令
输入和操作输出等公共功能的一些封装;
● \lib\ExamApi.lib:是一个LIB 库文件,其中实现了对自动化阅卷功能
的一些封装;
● \src\api.h:头文件,定义了考生可能用到的的宏、枚举、结构、函数声
明;
● \src\SubwayCharge.h:头文件,定义了考生可能用到的的宏、枚举、
结构,以及需要考生实现的接口函数声明。考生可以向其中添加自己的定义。具体要求请看函数注释。
● \src\SubwayCharge.cpp:源码文件,提供了需要考生实现的接口函数
框架,这些函数是空白的,需要由考生实现。 ● 其他文件是VC 工程自行产生的,考生不必关注。
更详细的定义请参阅VC 工程。