数组中最大的子数组之和2
一、程序分析
(一)、要求
1,以指定格式的文本文件形式输入数组。
2,数组由一维变为二维。
3,熟练使用git常用命令将作业签入代码版本控制平台。
4,给出单元测试/代码覆盖率的最终覆盖率的报告,撰写博客。
(二)、实现代码
package test; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class Calculate { public static void main(String[] args) throws IOException { Integer[][] c = new Integer[100][]; c = ReadFile("C:\\Users\\玉玉的凉茶\\Desktop\\arr.txt"); for (int i = 0; i < c.length; i++) { for (int j = 0; j < c[0].length; j++) { System.out.print(c[i][j] + " "); } System.out.println(); } // System.out.print(c[2][2]); System.out.println("max:" + GetMaxSUM(c)); // System.out.println("2"+MaxSUM(c)); } public static Integer[][] ReadFile(String str) { FileReader file = null; try { file = new FileReader(str); } catch (FileNotFoundException e) { e.printStackTrace(); } System.out.println("文件测试数据如下:"); BufferedReader br = new BufferedReader(file);// 读取文件 try { String line = br.readLine();// 读取一行数据 int lenx = Integer.parseInt(line);// 将数据转化为int类型 line = br.readLine();// 读取一行数据 int leny = Integer.parseInt(line);// 将数据转化为int类型 // System.out.println(lines); String[] sp = null; String[][] c = new String[lenx][leny]; Integer[][] cc = new Integer[lenx][leny]; int count = 0; while ((line = br.readLine()) != null) {// 按行读取 sp = line.split(" ");// 按空格进行分割 // System.out.println("Length:"+sp.length); // System.out.println("sp:"+sp[0]); for (int i = 0; i < sp.length; i++) { c[count][i] = sp[i]; } count++; } for (int i = 0; i < lenx; i++) { for (int j = 0; j < leny; j++) { cc[i][j] = Integer.parseInt(c[i][j]); // System.out.print(cc[i][j]+" "); } // System.out.println(); } return cc; } catch (IOException e) { e.printStackTrace(); } return null; } public static int GetMaxSUM(Integer[][] a) { int n = a.length; int m = a[0].length; // 分块 Integer[] Max = new Integer[100]; Integer[] Begin = new Integer[100]; Integer[] End = new Integer[100]; Integer[] b = new Integer[100]; for (int i = 0; i < n; i++) { // 按行分组 for (int j = 0; j < m; j++) { b[j] = a[i][j]; } MaxIntArray(b, Max, Begin, End, m, i); } int max = Max[0]; for (int i = 0; i < n - 1; i++) { if ((Begin[i] <= End[i + 1] && Begin[i] >= Begin[i + 1]) || (End[i] <= End[i + 1] && End[i] >= Begin[i + 1])) { max = Max[i + 1] + max; } else { // 如果不能直接连通,判断代价是否合适 if (Begin[i] > End[i + 1]) { int t = Begin[i] - End[i + 1]; int s = Begin[i]; int temp = 0; for (int k = 0; k < t; k++) { temp += a[i + 1][s - k]; } if (temp + Max[i + 1] > 0) max = temp + Max[i + 1]; } if (End[i] < Begin[i + 1]) { int t = Begin[i + 1] - End[i]; int s = End[i]; int temp = 0; for (int k = 0; k < t; k++) { temp += a[i + 1][s + k]; } if (temp + Max[i + 1] > 0) max = temp + Max[i + 1]; } } } return max; } public static void MaxIntArray(Integer[] a, Integer[] max, Integer[] begin, Integer[] end, int n, int index) { Integer[] Max = new Integer[100]; Max[0] = 0; int i = 0;// 数组下标 int j = 0;// 最大值数组下标 int temp = 0;// 中间变量 // 记录子数组的起始位置和末位 // Integer[] Bg=new Integer[100]; Integer[] Bg = { -1, -1, -1, -1, -1 }; Integer[] Ed = new Integer[100]; while (i < n) { if (temp + a[i] >= Max[j]) { temp = temp + a[i]; Max[j] = temp; if (Bg[j] == -1) Bg[j] = i; Ed[j] = i; i++; } else if (temp + a[i] < Max[j] && temp + a[i] > 0) { temp = temp + a[i]; i++; } else if (temp + a[i] <= 0) { i++; j++; Max[j] = 0; temp = 0; } } max[index] = Max[0]; int q = 0; for (int k = 0; k <= j; k++) { if (Max[k] > max[index]) { max[index] = Max[k]; q = k; } } begin[index] = Bg[q]; end[index] = Ed[q]; } }
(三)、测试代码
package test; import org.junit.Test; import static org.junit.Assert.*; import static test.Calculate.GetMaxSUM; import static test.Calculate.ReadFile; public class CalculateTest { @Test public void test1() { String str="C:\\Users\\玉玉的凉茶\\Desktop\\arr1.txt"; Integer[][] c=ReadFile(str); System.out.println("MaxSUM:"+GetMaxSUM(c)); } @Test public void test2() { String str="C:\\Users\\玉玉的凉茶\\Desktop\\arr2.txt"; Integer[][] c=ReadFile(str); System.out.println("MaxSUM:"+GetMaxSUM(c)); } @Test public void test3() { String str="C:\\Users\\玉玉的凉茶\\Desktop\\arr3.txt"; Integer[][] c=ReadFile(str); System.out.println("MaxSUM:"+GetMaxSUM(c)); } @Test public void test4() { String str="C:\\Users\\玉玉的凉茶\\Desktop\\arr4.txt"; Integer[][] c=ReadFile(str); System.out.println("MaxSUM:"+GetMaxSUM(c)); } }
二、单元测试验证程序的正确性、以及运行结果截图
(一)、创建测试用例
(二)、测试结果
三、代码覆盖率
(一)、Jacoco插件安装
在Eclipse下依次点击 Help->Eclipse Marketplace->搜索EclEmma,图片如下:
(二)、覆盖率检测
1、对程序代码进行检测:
(三)、对测试代码进行检测
注意:绿色区域:代码被执行过;黄色区域:代码部分被执行过;红色区域:代码没有被执行过。
(四)、覆盖率测试成功后会出现代码覆盖率的统计信息,如下图所示:
由此图我们 可以看到:每个方法中执行到的代码和未执行的代码,可以看到代码测试覆盖率。看代码,是取得随机数,if判断可能出现不满足,可能满足的情况, 需要多次执行该代码,得到多次的代码覆盖率,然后吧多次得到的覆盖率合并,得到这个类总的代码测试覆盖率。
四、总结
1、通过Eclipse插件可以快速验证测试用例的代码覆盖率,在大型项目中,合格的测试用例覆盖率能够很好的减少因临时修改代码而导致的重大BUG,但不建议盲目追求代码覆盖率,尤其是中小型项目。
如果要测试整个项目中代码的测试覆盖率,可能比较麻烦,至少需要吧所有代码的测试类执行一遍,并且把所有代码执行的路径都考虑到才准确。
2、别忘记测试异常情况,空指针,或者其他异常后,执行异常代码,也会增加代码测试覆盖率的。
3、如果得到代码测试覆盖率比较高,显而易见能看出代码安全性会比较能保证。