本项目Github地址(同时包括两个作业项目):

Assignment03 -- https://github.com/Oberon-Zheng/SoftwareEngineeringAssignments

  1. st=>start: Start
  2. e=>end: End
  3. cond=>condition: Option
  4. op1=>operation: solution_1
  5. op2=>operation: solution_2
  6. st->cond
  7. cond(yes)->op1->e
  8. cond(no)->op2->e

测试案例

A - 最大子列和(Sum of the maximum subarray)问题

问题: 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n

例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。

- Baidu Baike

关于我个人对于此问题的算法考虑我将另起一个博文(会吾倚马万言,易此帜以外链)发布,这里直接使用Kadane算法(使用Python完成的一个子程序,这里改写为C++的)加以实现,关于这个算法的具体实现细节将同样在那篇博客连同我自己的想法一同发布,这里先给出这个程序的流程图(根据mermaid语法绘出):

I'll be your mermaid, caught on your rod

- Memorized Mermaid

- Scott Skott

注意,由于cnblogs的mermaid组件需要经过google的code analytics服务器,因此在转换为正确的流程图之前需要花费一段时间

So, stay tuned, plz!

我有雅各布的天梯,我天下无敌,我藐视银河系

ESO黑洞警告

graph TD
start(开始)-->inputarry>"传入arry"]
inputarry-->domakeres["(rb:RangeBlock):={sum:=0,start:=-1,end:=-1}"]
domakeres-->tryempty{"arry.size()=0?"}
tryempty-->|true|return>"返回rb"]
return-->e("结束")
tryempty-->|false|init["maxsum=0<br />sum=0<br />kickoff=0<br />i=0"]
init-->tryloop{"i&gt;arry.size()"}
tryloop-->|true|accumulate["sum:=arry<br />若sum&lt;0则sum:=0"]
accumulate-->max["maxsum:=max{sum,maxsum}"]
max-->tryneg{"arry[i]是负的同时arry[i]的绝对值大于原来sum<br />(sum=0且arry[i]&lt;0)"}
tryneg-->|true|rststart["kickoff:=i+1"]
tryneg-->|false|inhale["rb.start:=kickoff<br />rb.end:=i"]
sendmax["rb.sum:=maxsum"]
inhale-->sendmax
rststart-->sendmax
sendmax-->return

上述程序能够求得关于传入序列arry的一个最大子列和(下文简称最大和),并且能够得到这个最大子列在arry中的位置。

案例实现

本案例以C++语言加以实现,代码如下:

  1. ///File : MaxSubarray.h
  2. #pragma once
  3. #include <vector>
  4. using namespace std;
  5. struct RangeBlock
  6. {
  7. int sum;
  8. int start;
  9. int end;
  10. };
  11. /// File : MaxSubarray.c
  12. #include "MaxSubarray.h"
  13. #define POSCLIP(X) (X>0)?X:0
  14. #define MAX(X,Y) (X>Y)?X:Y
  15. using namespace std;
  16. RangeBlock MaxSubArray(vector<int> arry)
  17. {
  18. RangeBlock rb = { 0,-1,-1 };
  19. if (arry.size() == 0)
  20. {
  21. return rb;
  22. }
  23. int maxsum = 0;
  24. int sum = 0;
  25. int kickoff = 0;
  26. for (int i = 0; i < arry.size(); i++)
  27. {
  28. sum = POSCLIP(sum + arry[i]);
  29. maxsum = MAX(sum, maxsum);
  30. if (sum == 0 && arry[i] < 0)
  31. {
  32. kickoff = i + 1;
  33. //rb.end = rb.start;
  34. }
  35. else if(sum == maxsum)
  36. {
  37. rb.start = kickoff;
  38. rb.end = i;
  39. }
  40. }
  41. rb.sum = maxsum;
  42. return rb;
  43. }

这个程序传入一个标准库vector<int>容器作为输入(之所以使用vector是因为vector的长度可变),然后通过一个RangeBlock型对象返回最大子列的和与区间。

根据上面的流程图,这里面存在一个长度不定的循环,并且在循环内仍然有一个分支,因此这里面想要对循环内的所有可能情况做出测试是不可能的,因此for内的测试仅对若干种条件组合(每个数据会分别将覆盖内部的三个分支)。

单元测试

本单元测试将满足判定-条件覆盖(所有的判定都走一次,所有的条件分两个分支都满足一次)

归纳上述代码可以得到如下的条件判定列表:

  1. arry.size()==0 <---> arry.size()!=0 --[1]
  2. i < arry.size() <---> i >= arry.size() --[2]
  3. sum==0 <--->sum!=0 --[3]
  4. arry[i]<0 <---> arry[i] >=0 --[4]
  5. sum == maxsum <---> sum != maxsum --[5]

根据代码的执行情况来看,其中[3]和[4]存在条件组合,实际上当[3]的左命题成立时,[4]的右命题一定不成立,同时若[2]右、[3]右、[4]左成立则[5]左一定不成立arry[i]<0,maxsum>=sum ==>> sum+arry[i]<maxsum),而[2]的命题在执行一句for循环的时候总会有成立和不成立(维持循环和跳出循环),对于上述推断为一定不成立的关系下,无法找出具体的测试用例(因为是逻辑关系制约的不可能发生,比如我无法找到sum==0 && arry[i]>0的测试数据,因为根本写不出来,除非遭到某种硬件错误导致arry[i]或者sum发生翻转,但这不是单元测试能够解决的),对于for的测试主要聚焦于OBOE问题(一步之差),而当[1]的前命题成立时,实际上之后的条件实际上都走不到,但如果必要考虑后面的条件的话,实际上只能讨论i>=arry.size(),for循环实际上也执行不了,因此我们归纳出如下的条件组合:

  1. arry.size() == 0 --[S1]
  2. arry.size() != 0 && sum == 0 && arry[i]<0 && sum == maxsum --[S2]
  3. arry.size() != 0 && sum == 0 && arry[i]<0 && sum != maxsum --[S3]
  4. array.size() != 0 && sum != 0 && arry[i] < 0 && sum != maxsum --[S4]
  5. array.size() != 0 && sum != 0 && arry[i] >= 0 && sum == maxsum --[S5]
  6. array.size() != 0 && sum != 0 && arry[i] >= 0 && sum != maxsum --[S6]

单元测试将围绕[S1]到[S6]产生测试数据如下:

S1 S2 S3 S4 S5 S6
空数组 全负数组 第一个负数 有正数的时候加入负数 加入非负数(开始) 加入非负数(继续加入)

根据上述归纳,编订了如下的测试数据:

  1. #include "stdafx.h"
  2. #include "CppUnitTest.h"
  3. #include "..\Assignment03\MaxSubarray.h"
  4. using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  5. namespace UnitTestA03
  6. {
  7. TEST_CLASS(UnitTest1)
  8. {
  9. public:
  10. TEST_METHOD(TestEmpty) //S1
  11. {
  12. std::vector<int> a;
  13. RangeBlock rb = MaxSubArray(a);
  14. Assert::AreEqual(rb.sum, 0);
  15. Assert::AreEqual(rb.start, -1);
  16. Assert::AreEqual(rb.end, -1);
  17. }
  18. TEST_METHOD(TestAllNegative) //S2
  19. {
  20. std::vector<int> a = { -1,-5,-8,-10,-6,-40,-1630,-5 };
  21. RangeBlock rb = MaxSubArray(a);
  22. Assert::AreEqual(rb.sum, 0);
  23. Assert::AreEqual(rb.start, -1);
  24. Assert::AreEqual(rb.end, -1);
  25. }
  26. TEST_METHOD(TestAllZero) //S4
  27. {
  28. std::vector<int> a(10, 0);
  29. RangeBlock rb = MaxSubArray(a);
  30. Assert::AreEqual(rb.sum, 0);
  31. Assert::AreEqual(rb.start, 0);
  32. Assert::AreEqual(rb.end, 9);
  33. }
  34. TEST_METHOD(TestOscillating) // S3和S5
  35. {
  36. std::vector<int> a = {0, 1,-2,3,-4,5,-6,7 };
  37. RangeBlock rb = MaxSubArray(a);
  38. Assert::AreEqual(rb.sum, 7);
  39. Assert::AreEqual(rb.start, 7);
  40. Assert::AreEqual(rb.end, 7);
  41. }
  42. TEST_METHOD(TestInhaling) // S4和S5
  43. {
  44. std::vector<int> a = {1, 3,-2,-3,0,0,-6,-10 };
  45. RangeBlock rb = MaxSubArray(a);
  46. Assert::AreEqual(rb.sum, 4);
  47. Assert::AreEqual(rb.start, 0);
  48. Assert::AreEqual(rb.end, 1);
  49. }
  50. TEST_METHOD(TestNormal) //综合测试
  51. {
  52. std::vector<int> a = { 1,3,2,-4,0,5,8,-1,-10 };
  53. RangeBlock rb = MaxSubArray(a);
  54. Assert::AreEqual(rb.sum, 15);
  55. Assert::AreEqual(rb.start, 0);
  56. Assert::AreEqual(rb.end, 6);
  57. }
  58. };
  59. }

最终各测试均通过:

Kadane算法在\(\omicron(n+k)\)的复杂度下得到了正确的结果。

B - 阶梯营业税问题

下表为某商场每日营业额与应收税率的对照表,请编写一小程序根据该商场每日营业额计算其实际应缴纳税费。

营业额X/¥|税率

:---

软件工程第3次作业——Visual Studio 2017下针对代码覆盖率的C/C++单元测试的更多相关文章

  1. 软件工程第2次作业——Visual Studio 2017下基于C/C++的VSTS单元测试实践

    Write one minute, test all day long. 环境确定 IDE:Microsoft Visual Studio 2017 Community 语言:C++ 单元测试工具:V ...

  2. Win10 + Visual Studio 2017 下 OpenCV无法显示图像的问题

    测试代码如下: #include "stdafx.h" #include<opencv2\opencv.hpp> #include<opencv2\highgui ...

  3. vue.js在visual studio 2017下的安装

    1.打开"工具"菜单->"NuGet 包管理器"->"管理解决方案 Nuget 的程序包": 在红色标识的地方输入vue: 2. ...

  4. Visual Studio 2017 Enterprise (15.3)

    版本15.3更新在用户离线下载时更加人性化,包含了进度显示,下载出错可以输入R,进行下载的重新尝试,并在当前下载框下继续下载为完成的作业,结合 --layout 参数的离线文件的检查和修复,并且在下载 ...

  5. 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序

    如何在Visual Studio 2017中使用C# 7+语法   前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...

  6. 深入研究Visual studio 2017 RC新特性

    在[Xamarin+Prism开发详解三:Visual studio 2017 RC初体验]中分享了Visual studio 2017RC的大致情况,同时也发现大家对新的Visual Studio很 ...

  7. Xamarin+Prism开发详解三:Visual studio 2017 RC初体验

    Visual studio 2017 RC出来一段时间了,最近有时间就想安装试试,随带分享一下安装使用体验. 1,卸载visual studio 2015 虽然可以同时安装visual studio ...

  8. Microsoft Visual Studio 2017 for Mac Preview 下载+安装+案例Demo

    目录: 0. 前言 1. 在线安装器 2. 安装VS 3. HelloWorld 4. ASP.NET MVC 5. 软件下载 6. 结尾 0. 前言: 工作原因,上下班背着我的雷神,一个月瘦了10斤 ...

  9. Create an offline installation of Visual Studio 2017 RC

    Create an offline installation of Visual Studio 2017 RC ‎2016‎年‎12‎月‎7‎日                             ...

随机推荐

  1. PAT 天梯赛 L1-043 阅览室

    L1-043. 阅览室 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 天梯图书阅览室请你编写一个简单的图书借阅统计程序.当读者 ...

  2. bat文件【java调用】

    Runtime.getRuntime().exec("cmd /c del c:\\a.doc");   //Runtime.getRuntime().exec("not ...

  3. Serializable在C#中的作用及其优点

    原文发布时间为:2009-10-27 -- 来源于本人的百度文章 [由搬家工具导入] Serializalbe - Enable the object can be Serialized into a ...

  4. Java中Vector笔记

    Vector和ArrayList Vector和ArrayList在使用上非常相似,都可用来表示一组数量可变的对象应用的集合,并且可以随机地访问其中的元素.   Vector的方法都是同步的(Sync ...

  5. Scrapy笔记:CrawSpider中rules中的使用

    scrapy.spiders.crawl.CrawlSpider类的使用 这个类比较适用于对网站爬取批量网页,相比于Spider类,CrawlSpider主要使用规则(rules)来提取链接 rule ...

  6. 倒计时器CountDownLatch与同步屏障CyclicBarrier

    CountDownLatch CountDownLatch是一个非常实用的多线程控制工具类,这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行.在这里指CountDownL ...

  7. LeetCode OJ-- 3Sum **

    https://oj.leetcode.com/problems/3sum/ 在一个数列中,求出所有3个数之和是0的3个数. 刚开始给自己挖了坑,由于没闹清,unique()函数的含义,去掉重复不彻底 ...

  8. 2017广东工业大学程序设计竞赛决赛 F(LCA + 斐波那契数列性质)

    不能组成三角形的极端数列:1,1,2,3,5,8,13,21,……到第50项时候肯定到1e9了…… 如果两个点之间距离大于50,则直接Yes…… 否则的话直接暴力取出所有边,然后升序排序,判断一下就可 ...

  9. Apache/Nginx为PHP设置、添加$_SERVER服务器环境变量

    在PHP开发中为了区分线上生产环境还是本地开发环境, 如果我们能通过判断$_SERVER['RUNTIME_ENVIROMENT']为 'DEV'还是'PRO'来区分该多好, 可惜的是$_SERVER ...

  10. [js]数组栈和队列操作

    写在前面 在项目中,对数组的操作还是比较常见的,有时候,我们需要模拟栈和队列的特性才能实现需求,这里记录一下这个知识点. 栈 栈(stack)又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一 ...