超市收银系统 Supermarket POS system
本次大作业是利用 C++语言,基于 FLTK 图形库来设计超市收银系统。首先介绍程序的设计思想:
这套程序完全是基于题目所给的要求逐条逐步设计的。我把程序实现大致分为数据层面和图形层面。
数据层面:
程序使用的 Class 一览表
1.基本信息包括商品名称、商品类别、条形码号、单价、计量单位、进价、库存、备注等项。要求能够新增、删除 、修改、检索商品信息,能够检测非法条形码号并防止录入重复信息,允许以文件形式批量导入、导出商品信息。
题目中描述的基本商品对应的是上图中的 Goods 类,类中成员以及成员函数功能基本上和名字一一对应。
可以看出 Goods 类其实是对于一种商品的描述,而超市的商品实际上是 Goods 类的一个集合,因此,对于超市中所所有商品,这里定义了一个 vector来实现,并且该 Goods 向量名字也很形象:Warehouse(仓库)。
定义了该向量之后,搜索商品则变得十分容易,只需通过迭代器遍历访问 Warehouse 即可,而删除商品则是通过将商品信息置为非法值来达到的。
至于检测非法条形码号并防止录入重复信息,这里首先要说明的是,出于编程工作量以及实际商场运作 的考虑,没有提供手动输入商品信息的接口。检查条形码的工作实际放到了从文件导入商品信息的过程中。
可见上述代码分别进行了条形码检测(位数是否符合)以及是否重复的检查,该套程序默认有效条形码是八位整数(eg.10239523)。
至于从文件输入输出,这在之前的上机题目中已经有类似的练习,直接利用文件流便可以达成。
2.生成一次购买物品清单,包括消费日期、物品名称、单价、数量、总价等。 收银找银功能,根据收入金额计算找银金额。
对于物品清单,仍旧是文件操作,生成的收据清单样例如下
其中涉及的类有 Date 类,专门用来管理和日期相关的操作。同时,针对购买行为也专门涉及了
Purchase_action 类,这样可以将商品和日期之间关联起来。方便后面进行统计操作。
3.根据选择的时间跨度,生成营业报表。包括总营业额、利润曲线、各类商品的收益比重等统计功能
关于搜寻给定日期内的消费记录( Purchase_action ) , 由于在进行消费的时候创建了
Purchase_action 的向量,因此也是在该向量(History)中进行迭代器遍历,寻找对应日期以及对应商品的利润信息。此处需要注意的是,按商品归类的利润存储在 Goods 类的成员 profit 中,而按日期归类的利润则存贮在 ProfitPerDay 类中。
图形层面:
仔细阅读 main 函数会发现,该函数中主题部分都是定义 FLTK 库中的对象。此处主要说明程序中用到的一些对象:
Fl_Input
这个类是 FLTK 库中用来管理图形界面输入的。其中用到的具体类有:
Fl_Int_Input
用于定义仅仅能输入整数的输入框(0-9)。
Fl_Float_Input
用于定义仅仅能输入浮点数的输入框(0-9 & . )。
创建这些对象的时能够生成图形界面的文本输入框,而 FLTK 的事件触发(按下按钮,敲击回车, 输入框数值改变等)是通过调用对象的 when 函数(不仅仅对于 Fl_Input 类,对所有的可互动类均是如此)。而触发之后的操作则是通过配置该对象的 callback 函数来实现。举例而言,如果要读入某个输入框的输入值,那么需要针对该输入框(对象)写一个读入(变量赋值)函数,并且将函数作为形参传递给 callback 函数。这些函数统一都放在了 FLTK_functions.h 文件中。
Fl_Output
如其名所示,是用于管理 FLTK 输出的类。本程序中利用该类来生成输出文本框。改变其输出值只用调用其成员函数 value 即可。
Fl_Button
如其名所示,是用于管理 FLTK 按钮的类,使用按钮的原因是显式地告诉用户如何进行操作,直接按回车等方法总是容易让人感觉不直观,也不容易知道操作的是哪一部分。因此,按钮的作用是将输入和输出进行关联。
Fl_Box
这个类在本程序中的作用主要是标清楚各个区域,让用户比较直观地找到在哪里搜索,在哪里消费,在哪里查看统计信息。
至于绘图以及输出各个商品所占利润百分比,程序中采用的是 fl_draw 系列的函数。需要注意的是,FLTK 并不支持直接调用这些函数进行绘图,必须将其作为用户自定义类中的成员函数才能使用。这也是程序中 profitCurve 类的设计初衷。
最后附上一张程序运行结果图:
关于在Xcode中配置FLTK库
其实配置FLTK库才是比较重要的一点。在MacBook上使用过Visual Studio,按照老师主页上的配置确实可以使用FLTK库。但奈何自己的MacBook跑一会Windows就变铁板烧,所以还是想用Xcode,但无奈网上并没有很直接的教程,因此打算自己在这里记录一下。
这里使用的是Xcode 8.2.1 + FLTK 1.3.4,下载FLTK 1.3.4解压之后,打开./ide/Xcode4/FLTK.xcodeproj ,Xcode选择Automatically Create Schemes.注意这张图中的FL文件夹,我们待会需要用到。
对于FLTK开发不是很熟悉的同学(比如我),上图中左侧的Tests文件夹下全是例程,可以参考,看几个例程(input,output,line_style)之后,基本上FLTK的套路能学个大概。
如果想要运行例程,在下图中点击browser(因为我这里选的是browser...)然后在下拉菜单里选择你想要执行的Scheme,编译运行即可。Scheme对应的源码可以在上述Tests下同名文件夹中找到。
打开这个FLTK.xcodeproj目的主要是为了编译出FLTK的库,我也是自己胡乱摸索出来的,可能有更好的办法,下面讲一下具体过程。
给出的例子是绘制红白相间的棋盘,我已经将源代码上传到tutorial文件夹下。
1.首先,在打开的FLTK.xcodeproj中任选一个Scheme,在Xcode顶部标签Product下选择Archive(图中所示为"hello"这个scheme生成的),编译完毕后会显示如下窗口:
2.选择Export,弹窗中选择
3.点击Next,然后在你保存库的地方,就会出现一个文件夹,点进去之后,右键hello("hello"这个scheme生成的),选择"显示包内容",进入Content/Frameworks就可以看到FLTK的库了,请务必记得将这个fltk.framework文件拷贝出来。
4.接下来我们就要将这个库和自己的Project关联起来,首先创建一个Command line tool 的 Project(FLTK_Tutorial),导入红白棋盘的源文件,在project的选项中选择Build Phase,在 Link Binary with Libraries中,选择"+"。
5.在Add Another...中选择刚刚拷贝出来的fltk.framework
如果此时编译,会提示找不到头文件,因此,接下来要做的是将FLTK的头文件包含到Project中,考虑到未来可能还要使用FLTK库,这里是将FLTK添加到系统的framekwork中。
6.将fltk.framework文件拷贝到 /Library/Frameworks文件夹下,可以看到这个文件夹下有很多framework文件夹,注意此步骤需要管理员权限
7.比较蛋疼的是,这个fltk.framework中虽然已经包含了头文件,但是并不全(142个),差一个abi-version.h文件,因此,我们回到最初的FLTK解压文件夹,在/FL文件夹中找到abi-version.h文件,然后再回到/Library/Frameworks下,打开刚刚拷贝进来的fltk.framework,在/Version/A/Headers/FL/ 下,将abi-version.h拷贝进来。
8.集齐了头文件之后,我们需要在Xcode中设定头文件搜寻路径。还是在Project的选项中,这次选择Build Setting,在Search Paths中按照下图进行设置。
设置完毕后理论上编译就可以执行了。效果如图: