写在前面:关于结对编程


结对编程我一直认为是一种非常好的合作方式,他的形式主要是由一个人负责代码编写,另一个人则在一旁即时对写下的代码进行审查,这样可以大大减少代码实现方面的错误。

这次我的结对伙伴是小芦荟(学号后四位为1221)。他平时喜欢打篮球,打的也挺不错的,三国杀也是高手(都100多级了),是一个比较靠谱的人。但是在编程这方面他可能不太擅长,因此这次结对项目就变成了我一个人写,他在旁边看着……不过有时他也会指出我的代码中非常明显的问题,这也保证了我的代码正确性较高。设计的单元测试几乎全是一次通过。

附结对编程图片:

关于Design by Contract、Information Hiding


本次结对项目要求对上次的个人项目进行封装,并写一个界面来调用这些封装好的函数。这就需要我们对相关接口制定一个规范,我和另一个队伍(pair16)的同学约定好了代码接口,便于之后的测试。

对于Information Hiding原则,我们这次其实做的并不好,所有的类属性也均为public,这主要考虑到本次程序会封装为程序编写的方便。

我们core部分均采用Win32 Console Application实现,图形界面部分均采用MFC Application实现。core编写完成,测试完成后,生成dll并提供两个接口,用来实现要求的两个功能。接口的定义均提前约定。

关于接口定义、dll封装的具体内容在第二篇博客中会详细介绍。

设计与实现


算法设计

我们本次项目沿用了上次我的个人项目的设计,只不过在其基础上添加了对负数、有无括号、有无乘除法的限制,以及对运算符个数的限制。

具体来说,对于四则运算题目生成的部分:

  1. 获取到传入的参数限制,包括运算符个数限制、数值限制、有无分数、有无负数
  2. 递归生成一个表达式树
  3. 递归进行表达式的正确性检验(是否出现了负数、除0以及不能整除的情况)
  4. 递归对表达式树进行最小表示
  5. 如果得到的算式之前没有生成过,则将该算式加入到生成队列中。
  6. 如果当前的表达式个数已经达到要求,则将表达式与答案返回。

其中,在生成表达式树的过程中,首先需要判断树中当前的节点是否为分支节点(即运算符)。如果当前的树的总结点数为0,那么该节点必须为分支节点,如果当前树中的分支节点已经打到了要求的上限,则该节点必须为叶子结点(即操作数)。有了这个信息之后,针对当前结点的类型不同,就可生成对应的结构,之后如果当前结点为分支节点的话,就递归生成其左右子树。

在对表达式进行正确性检验的过程中,如果当前结点为叶子节点,那么我们仅需要检验这个叶子结点的数值是否满足要求。否则,先递归对它的左右子树进行正确性检验,在确保左右子树正确的情况下,检验当前结点的运算是否会造成不合法的情况,如果有的话则进行修复。

在对表达式最小表示的过程中,同样是先递归对其左右子树进行最小表示,之后再看,如果当前结点为'+'或'×',则判断一下他的两个子树的hash值大小,在不改变运算顺序的前提下使表达式变为最小标识的形式。

检验算式仍然采用了第一次作业的形式,以一个STL的set来存放最小表示后的字符串,通过字符串的比较进行判重。

对于计算表达式结果的功能,仍然没什么好说的,采用了STL的两个栈来维护。

具体实现

首先来看UML类图:

本次项目中共用到了4个类。CFactor类是对上次Factor的一个扩展,加入了对负数的支持。CExpressionNode类是表达式树的一个节点。CExpression类是表达式树,CProblemSet类对两种操作进行了封装。这四个类形成如上的关联关系。

根据这个这个类图,顺便说一下本次结对项目的代码规范:

  1. 类名均以 C 开头,大括号不换行
  2. 类属性以 m _ 开头
  3. 类方法均使用小写字母,单词之间采用下划线分开。
  4. 每个类方法前必须有必要的注释

这样的规范主要考虑到本次项目要与MFC结合,因此使用了一些Win32的代码习惯。

CFactor类中,我重载了各种运算符,包括输入输出、四则运算和比较运算符。重载运算符后会大大降低编程复杂度,但是过多地采用流输入输出可能会对程序效率造成影响……这也是我在测试的时候才发现的问题。

CExpressionNode类则没什么好说的,就是储存了一个树节点的信息,包括其左右子树、当前结点的运算符以及当前子树的表达式的值。

CExpression类则是一个表达式树,他内部采用了一个CExpressionNode类型的数组用来存储表达式中的所有结点,并通过new_node方法实现获取一个新节点的操作。这样做避免了每次的动态内存分配,一定程度上可以提高程序效率,但是这样做则要求表达式不能太长,不过在实际应用中不会用到太长的表达式。

CProblemSet类则没什么好说的了,他实例化了一个CExpression类的对象,每次调用该类的 build_expression_tree 方法生成一个表达式并使用set进行重复检验。

单元测试


本次项目的基础就是CFactor类,如果该类的实现有问题,那么所有功能都不能正常工作,因此我主要对该类进行了单元测试。

VS2013单元测试我也是第一次使用,不知道为什么Managed Test Project 创建后会无法连接C++console Application的代码,最后采用了 Native Unit Test Project 来做单元测试,它的语法与Managed Test Project略有不同,但是也很简单,我针对CFactor类的各种方法写了37条Unit Test, 并且全部通过了。

代码覆盖率:

注:我的VS2013是社区版,没有代码覆盖率分析工具,所以在我编写完测试用例后,借用了同寝室的另一个人的电脑来测试并进行代码覆盖率检验。

结对项目——Core设计与实现的更多相关文章

  1. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  2. 系统分析与设计结对项目——WordCount

    结对项目完成WordCount 合作者:201631062507  201631062526(学号) 代码地址:https://gitee.com/WordCountMC/WordCountTeam ...

  3. 高级四则运算器—结对项目反思(193 & 105)

    高级四则运算器—结对项目反思(193 & 105) 本周我和一位韩国同学(71061105)一起结对编程完成了我们的结对项目——高级的小学四则运算题目生成器. PSP表格   PSP2.1 P ...

  4. 结对项目——图形界面实现与dll动态链接

    先来一发软件截图~~~ 生成题目的界面 测评界面 第三块本来准备做一个文件历史记录的界面,但是由于时间不够,暂时还没做完. 图形界面的设计与实现 由于对传统的对话框风格不太满意,所以这次作业的图形界面 ...

  5. [2017BUAA软工助教]结对项目小结

    2017BUAA结对项目小结 一.作业链接 http://www.cnblogs.com/jiel/p/7604111.html 二.评分细则 1.注意事项 按时间完成并提交--正常评分 晚交一周以内 ...

  6. [buaa-SE-2017]结对项目-数独程序扩展

    结对项目-数独程序扩展 step1~step3:github:SE-Sudoku-Pair-master step4:github:SE-Sudoku-Pair-dev-combine step5:g ...

  7. [2017BUAA软工]结对项目

    软工结对项目 一. Github项目地址 https://github.com/crvz6182/sudoku_partner 二. PSP表格 Psp personal software progr ...

  8. [2017BUAA软工]结对项目:数独扩展

    结对项目:数独扩展 1. Github项目地址 https://github.com/Slontia/Sudoku2 2. PSP估计表格 3. 关于Information Hiding, Inter ...

  9. [BUAA_SE_2017]结对项目-数独程序扩展

    结对项目-数独程序扩展 Runnable on x64 Only sudoku17.txt 须放置在可执行文件同目录中,可移步以下链接进行下载 Core-Github项目地址 GUI-Github项目 ...

随机推荐

  1. Linux运维之每日小技巧-检测网站状态以及PV、UV等介绍

    [root@ELK-chaofeng07 httpd]# curl -o /dev/null -w %{http_code}\\n -s www.baidu.com 状态码为200表示成功. PV.U ...

  2. SqlBulkCopy批量添加

    /// <summary> /// 添加数据 /// 注:DataTable列名必须和数据库列名一致 /// </summary> /// <returns>< ...

  3. java用星星符号打印出一个直角三角形

    package debug; public class Demo10 { public static void main(String[] args) { //用星星符号打印出一个直角三角形 for( ...

  4. 离线安装Cloudera Manager 5和CDH5(最新版5.9.3) 完全教程(五)数据库安装(双节点)

    一.方案选择 通过Lvs+keepalived+mysql(主主同步)实现数据库层面的高可用方案,需要两台服务器作为数据库提供业务数据的存储,应用服务器通过vip访问数据库,允许同一时间内一台数据库服 ...

  5. ROS 双目标定

    http://wiki.ros.org/camera_calibration/Tutorials/StereoCalibration 发布ZED节点 roslaunch zed_cpu_ros zed ...

  6. 查看和指定SpringBoot内嵌Tomcat的版本

    查看当前使用的Tomcat版本号 Maven Repository中查看 比如我们需要查Spring Boot 2.1.4-RELEASE的内嵌Tomcat版本, 可以打开链接: https://mv ...

  7. CVE-2017-5123 分析报告

    系统信息 系统:ubuntu 14.04 64位 内核版本:4.13 (KASLR关闭 但是参考文档一中的哥们已经提到如何绕过:利用对非法地址写的保护) 漏洞背景 CVE-2017-5123是一位葡萄 ...

  8. https安全协议原理

    那么什么是HTTPS? HTTPS(Hypertext Transfer Protocol Secure)是一种通过计算机网络进行安全通信的传输协议.HTTPS经由HTTP进行通信,但利用TLS来加密 ...

  9. Redis详解(六)------ RDB 持久化

     前面我们说过,Redis 相对于 Memcache 等其他的缓存产品,有一个比较明显的优势就是 Redis 不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,has ...

  10. 随机指定范围内N个不重复的数

    此为工具类,支持抽奖业务需求,具体实现见下方代码: package com.org.test; import java.util.ArrayList; import java.util.List; p ...