软件工程(2018)第三次个人作业

软件工程(2018)第三次个人作业


前方高能:本次作业中含有大量基础知识,请不要嘲笑我QAQ

第三次作业来了。选择看似相比有难度的(1)(其实是看不懂(2)在干什么)

题目要求:题目(1):最大连续子数组和(最大子段和)

背景
问题: 给定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。

读完题目,第一想到就是数组解决问题。定义数组a[]输入变量后,遍历数组,将数组每个元素分别开始向后逐步取和,将这些和存到数组b[]中,最后比较数组b[]中,取最大值即可。

看起来用到的方法都是数组的基本方法,第三次作业果然还是简单(心里长舒一口气)

所以我的代码构思是在某堂课上随手完成的,大体思路算法有了后,在自己计算机上实现就行

但是实现又遇到了各种问题,一些在C上容易实现的方法,在Eclipse上还没有试过

问题(1):Java中数组的定义(没错第一个问题就是这个)

解决:参考《疯狂JAVA讲义》。JAVA中数组可动态定义或静态定义,前者定义后分配指定个数个内存,后者定义后直接给数组赋值,由系统来确定分配多少个空间。

        int[] intArr;
        intArr=new int[] {5,6,8,20};//静态定义
        int[] intArr2= {5,6,8,21};//简化静态定义方式
        int[] intArr3;
        intArr3=new int[4];//动态定义
        int[] intArr4=new int[4];//简化动态定义方式

与此同时,我想着把JAVA中所有关于数组的基本方法学习一下,数组的输入输出当然是最重要的

输入:利用循环逐个输入元素,循环变量控制条件是数组的length变量,此时须注意动态定义中会使length有可能大于我们程序运行时要输入的元素个数,在此我有疑问,JAVA是否可以实现动态数组,我们先完成作业,然后再考虑这个

而JAVA中输入方法为下

        Scanner x = new Scanner(System.in);
        int n1=x.nextInt();

输出:利用循环遍历数组元素,逐个输出,输出方法如下

        System.out.println();//ln是换行

同时,了解到JAVA中有foreach循环遍历数组,看起来能简化代码

        for(int m:intArr)
            System.out.println(m);//foreach用法,注意m相当于一个临时变量,所以foreach方法无法完成数组的输入。

由问题(1)引发的关于数组的基本用法先学到这里,基本够用

这样程序代码可以写了,以下是我的程序代码

import java.util.Scanner;

public class Sz
{
    int n;//数组元素个数
    static int[] a=new int[10] ;//输入数组
    static int[] b=new int[10];//以每个元素为首元素的组合集
    public static void createArray(int n)//数组输入
    {
        for(int i=0;i<n;i++)
        {
            Scanner x = new Scanner(System.in);
            int n1=x.nextInt();
            a[i]=n1;
        }
    }
    public static int getMax(int i,int n)//生成数组第i个元素为首元素的组合最大的组合
    {
        int[] c=new int[10];//用于循环中求该元素为首元素的组合中最大的组合
        c[i]=a[i];
        for(int j=i;j<n-1;j++)
        {
            c[j+1]=c[j]+a[j+1];
        }
        for(int m:c)
        {
            if(b[i]<m)
                b[i]=m;
        }
        return b[i];
    }
    public static int getbMax(int[] b)//将b[]中最大元素筛选出来
    {
        int max=0;
        for(int m:b)
        {
            if(max<m)
                max=m;
        }
        return max;
    }

    public static void main(String[] args)
    {
        Scanner x = new Scanner(System.in);
        int n=x.nextInt();
        createArray(n);
        for(int i=0;i<n;i++)
        {
            getMax(i,n);
        }
        System.out.println(getbMax(b));
    }
}

附上程序运行截图

样例1:数组(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)

样例2:(a[1],a[2],a[3],a[4],a[5])=(-2,6,4,-7,-2)

注:以上代码是我最终版本代码,没以下问题,我是先写完程序再写博客,所以要保证代码都OK才会回忆我当时编程的心路过程(我觉得边写代码边写博客真的破坏思路,当然我的梦想是能边写边编而不影响思路,正如老师说过的直播写代码,我觉得OK)(我也有主播梦想)

写代码后调试修改了一些小错误,问题不大的,没有写出来。接下来碰到一个我不太理解的错误,虽然Eclipse强大的帮助修改能力教我将所以变量、方法加上static属性,但是我还是要弄懂有啥区别

问题(2)JAVA中static的用法

老规矩,上网学

这次应该是问题明确又基础,很容易找到回答

static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。

只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。

用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象市,不生成static变量的副本,而是类的所有实例共享同一个static变量。

static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用--废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。

static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,可以直接通过类名来访问,访问语法为:
类名.静态方法名(参数列表...)
类名.静态变量名

用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块(用处非常大,呵呵)。

1、static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。

两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。

所以一般在需要实现以下两个功能时使用静态变量:
?  在对象之间共享值时
?  方便访问变量时

2、静态方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,
因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。

例如为了方便方法的调用,Java API中的Math类中所有的方法都是静态的,而一般类内部的static方法也是方便其它类对该方法的调用。

静态方法是类内部的一类特殊方法,只有在需要时才将对应的方法声明成静态的,一个类内部的方法一般都是非静态的

以上内容摘自这篇博客(特意看了下欢迎转载,具体示例也有)

个人总结:static修饰的变量和方法称为静态变量,可以在类中直接引用变量、直接调用方法

问题解决后,经过测试也都ok,突然想到,我用Eclipse调试不像c一样熟练,而且我还没掌握Eclipse调试的方法

问题(3)Eclipse中如何调试

网上学习。Eclipse支持设置断点进行调试(否则程序直接运行到底)。右键代码行头数字设置breakpoint(或直接双击数字)(breakpoint更有详细设置,支持条件断点调试,有丶厉害啊这个)F5逐步调试,F6具体进入方法,F7跳出方法,CTRL+F2结束调试,嗯,我记住了

调试过程中,可将鼠标直接放在程序变量上显示变量,更可以设置出Variables窗口查看其余变量(Window——show view——Other——debug——Variables),这样跟C语言调试几乎完美相同了,或许有更多功能待挖掘

接下来是测试

覆盖方法

(1))语句覆盖:选择合适用例,所有语句被执行一次。

语句覆盖是指选择足够的测试用例,使得运行这些测试用例时,被测程序的每一个语句至少执行一次,其覆盖标准无法发现判定中逻辑运算的错误。

(2)判定覆盖:每个判定至少取一次真、一次假。

判定覆盖是设计足够多的测试用例,使得程序中的每一个判断至少获得一次“真”和一次“假”,即使得程序流程图中的每一个真假分支至少被执行一次。

(3)条件覆盖:每个条件的各种可能结果至少满足一次。

条件覆盖是指选择足够的测试用例,使得运行这些测试用例时,判定中每个条件的所有可能结果至少出现一次,但未必能覆盖全部分支。

(4)判定条件覆盖:同时满足判断覆盖和条件覆盖。

判定条件覆盖是设计足够的测试用例,得使判断中每个条件的所有可能取值至少执行一次,同时每个判断本身所有可能结果也至少执行一次。缺点是忽略了条件的组合情况。

(5)条件组合覆盖:所有组合情况都要覆盖一次。

在白盒测试法中,选择足够的测试用例,使得每个判定中条件的各种可能组合都至少出现一次。显然,满足“条件组合覆盖”的测试用例是一定满足“判定覆盖”、“条件覆盖”和“判定/条件覆盖”的。

选定的覆盖方法(判定/条件覆盖)我采用的是判定条件覆盖:

(1)max>b[] max>0

(2)max>b[] max=0

(3)max<b[] max>0

(4)max<b[] max=0

选择用例:

(1)测试用例:{-2,11,-4,9}
(2)测试用例:{-2,-3,-4,-5}
(3)测试用例:{1,2,3,4}
(4)测试用例:{-5,-4,-3,-1}

建立JUNIT测试单元,测试代码如下

import static org.junit.Assert.*;

import org.junit.Test;

public class SzTest
{
    int[] a=new int[] {-2,11,-4,9};
    static int[] b=new int[] {14,16,5,9};
    @Test
    public void testGetMax()
    {
        assertEquals(14,new Sz().getMax(0,4));
        assertEquals(16,new Sz().getMax(1,4));
        assertEquals(5,new Sz().getMax(2,4));
        assertEquals(9,new Sz().getMax(3,4));
    }
    @Test
    public void testGetbMax()
    {
        assertEquals(16,new Sz().getbMax(b));
    }
}

进行测试,出现问题(4)测试失败

如图

java.lang.AssertionError: expected:<14> but was:<0>

测试结果是0?不应该啊。于是设置断点逐步调试,发现问题。由于Sz中a[]是静态变量,在那个类中可以被程序直接引用修改。而在Sztest类的调用中,Sz的a[]的值一直为0。所以程序输出为0。为了测试用,我将Sz.getMax中临时定义a[]的值为{-2,11,-4,9}(仅测试用,不影响原程序),并且将Sztest中定义的a[]删除(这的a[]没有意义了),重新调试,OK。如图。

接下来将剩余测试测完,直接列图了

注:这里的0是因为都是负数,所以默认全用0取代

注:这里同理

单元测试完成!

后记:本次作业完成,问题也都圆满解决,最后调试出现的问题是靠自己调试分析完成有点成就感。下次见~!

对了,动态数组还没实现!

我觉得,如果能像建立链表一样建立一个元素,然后每次输入元素都连接上一个元素(链表靠地址连接,数组就靠建立数组时分配的连续内存这个顺序连接),输入结束后,数组也建立完成。通过思考和逐渐实践,我觉得可行,但是总感觉自己理解不深导致没有弄出来。最后在网上发现了跟我思路特别像的大佬实现了(侵删)

    // 定义一个初始长度为0的数组,用来缓存数据
    private String[] src = new String[0];
    // 增加
    public void add(String s)
    {
        //定义新数组,长度是原数组长度+1
        String[] dest = new String[src.length+1];
        //将原数组的数据拷贝到新数组
        System.arraycopy(src, 0, dest, 0, src.length);
        //将新元素放到dest数组的末尾
        dest[src.length]=s;
        //将src指向dest
        src=dest;
    }

豁然开朗,突然想起来C语言中例如a[]中的"a"实际上是一个地址,可以指向别的地址,这样我就可以将两个数组的"数组头"连接起来,模拟建立链表时光标的移动。不过我有疑问了:既然是指向,那原数组是不是应该及时删除从而减少内存呢?删除后才可以算做动态数组的完美建立。感觉又学到了丶东西。

本次作业也收获颇丰呢(最终代码)

原文地址:https://www.cnblogs.com/L1aw/p/8686341.html

时间: 2024-10-13 00:55:59

软件工程(2018)第三次个人作业的相关文章

软件工程(第三次作业)

软件工程(第三次作业) 组员:周德莉.王铭霞 一.题目 在之前编写的四则运算程序基础之上做如下改进: 1  请参照教材Page57:4.2-4.3节中内容,修改原程序,使之符合 “代码风格和设计规范”的基本要求: 2  请采用模块化设计思想,修改之前的code,将 “计算功能” 封装起来 小提示: 假如在C语言环境下,可将函数声明与具体实现分别存放在头文件(.h)和源文件(.c)中: 3  通过测试程序和API 接口,测试其简单的加法功能. 小提示: 单元测试方法请参看教材Page21:2.1.

第三次大作业-作业准备

在第二次大作业结束之后,第三次大作业-白盒测试实践在三周内进行. 由于大家刚进行完一次大作业的辛苦工作,于是本组决定第一周交由大家复习学习之前的黑盒测试实践.搜集资料.自发配置工作环境和工具.进行自己的数学课程复习以及实验室工作.在这段时间内,大家对选择的测试工具进行了一定的了解,在SPOC课程中进行视频学习,学习白盒测试相关的知识点,并在今晚进行了一定的整合. 预计将从明天起正式分工投入到这次作业的工作中! 一.白盒测试实践作业 (1)阶段一:熟悉白盒测试方法. (2)阶段二:熟悉代码复审的过

17秋 SDN课程 第三次上机作业

SDN 第三次上机作业 1.创建拓扑 2.利用OVS命令下发流表,实现vlan功能 3.利用OVS命令查看流表 s1: s2: 4.验证性测试 5.Wireshark 抓包验证 原文地址:https://www.cnblogs.com/qq952693358/p/8313497.html

2018.3.8课下作业

2018.3.8课下作业 相关知识点的总结 编写代码 mkdir用于新建文件夹 vi用于编写代码 esc:wq结束编写 上传码云 git add+文件名 git commit -m "说明" git push -f origin master pakeage注意 javac src/Hello.java -d bin编写至bin文件夹 java -cp bin is5227.Hello在bin文件夹中编译 课上内容的补做 作业:p14 结果截图 代码的功能:规定数的求和 作业:带包的代

【软件工程实践 &#183; 团队项目】 第一次作业

[软件工程实践 · 团队项目] 第一次作业 队员姓名与学号(标记组长) 学号 姓名 20165211 丁奕(组长) 20165208 孔月 20165230 田坤烨 20165226 刘香杉 队名 快奶我一口 队员风采: 全军出击!!!! 团队的首次合照 团队的特色描述 我们敲认真! 原文地址:https://www.cnblogs.com/KY-high/p/9000409.html

失物找寻APP软件需求规格说明书——第三次团队作业

?对于软件需求规格说明书的理解 在没写这份软件需求规格说明书的时候我们组成员都不是很理解它的必要性,当然,写完之后才知道它的作用. 软件需求说明书的存在是为了使用户和软件开发者双方对该软件的初始规定有一个共同的理解,双方进行理解和交流,反映出用户问题的结构,可以作为软件开发工作的基础和依据,并作为确认测试和验收的依据. 在写了这份软件需求规格说明书之后才更加明确我们项目的很多细节理解,包括它的背景.目的.项目产品的描述.功能描述.特点.具体需求.它的可用性等等,在正式做软件之前必须要把这些都细节

软工第三次团队作业

一.题目要求 参考发到群里的<软件需求规格说明书>范本,撰写本团队的软件需求规格说明书 不要照抄范本的内容,请参考它的形式,紧密结合本团队项目实质展开 使用UML工具进行描述,并保证符号.描述语言的一致性 请大家将报告发布在 "石墨文档" 中并将文档链接发布到博客中 推荐大家使用 https://www.draw.io 网站绘制UML图形(当然也可以使用Visio,但是毕竟邹老师要参与点评,大家还是对微软给予尊重 强烈推荐大家使用墨刀制作项目的原型 二.<软件需求规格

2018 年“三盟科技杯”中国大学生程序设计竞赛(湖南)

2018 年"三盟科技杯"中国大学生程序设计竞赛(湖南) A. Easy h-index 题目描述:给出一个数组\(a_i\),求最大的\(h\),使得至少有\(h\)个数不少于\(h\). solution 模拟. 时间复杂度:\(O(nlogn)\) B. Higher h-index 题目描述:写论文,当一份论文花费了\(x\)小时时,这份论文会得到\(ax\)个引用,\(a\)是给定的常数,\(x\)必须为正整数,每份论文都可以被之后自己写的论文引用,现在有\(n\)个小时写论

软件工程(2018)第三次团队作业

1. 题目要求 参考发到群里的<软件需求规格说明书>范本,撰写本团队的软件需求规格说明书 不要照抄范本的内容,请参考它的形式,紧密结合本团队项目实质展开 使用UML工具进行描述,并保证符号.描述语言的一致性 请大家将报告发布在 "石墨文档" 中并将文档链接发布到博客中 推荐大家使用 https://www.draw.io 网站绘制UML图形(当然也可以使用Visio,但是毕竟邹老师要参与点评,大家还是对微软给予尊重 :-) ) 强烈推荐大家使用墨刀制作项目的原型 2. 项目