欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

软件构造感想2

程序员文章站 2022-03-01 15:52:38
...

对给定的Java项目进行实现与升级

给出一个Java题目

给定研究人员的一系列论文(每个论文是一个非负整数),编写一个函数来计算研究人员的h-index数。(
根据维奇百科上h-index的定义:“如果科学家的N篇论文中的h篇中每篇至少被引用h次,而其他N-h篇论文中每篇不超过h篇引用,则h被称为科学家的h-index。”

  • 例子:
    输入: citations = [3,0,6,1,5]
    输出: 3
  • 说明:
    [3,0,6,1,5]表示研究人员总共有5篇论文,每篇论文分别获得3、0、6、1、5篇引用。 由于研究人员拥有3篇论文,每篇论文至少被3次引用,其余两篇论文每篇被引用不超过3次,因此她的h-index为3。
  • 注意:如果h有多个可能的值,则将最大值作为h-index。

解决思路、编写Java代码、执行

思路:先把数组从大到小排序,再从头遍历,找到符合要求的h-index值。
[3,0,6,1,5]→[6,5,3,1,0]
遍历时,如果数组中该位置的数值大于等于其序号+1,则h-index至少为序号+1。
例如:

  • 第0位为6,6>=1,则h-index=1;
  • 第1位为5,5>=2,则h-index=2;
  • 第2位为3,3>=3,则h-index=3;
  • 第4位为1,1<4,则h-index不再变化,算法终止。

先创建Java项目:

  • 在Eclipse中构造工程,命名为SC2020Spring_Classroom_Exercise;
    在src中创建包,命名为exercise_6_6;
    在包中创建类HIndex.java。

(1)控制台读入用户输入,按3,0,6,1,5的格式,存储于数组

Scanner scanner = new
Scanner(System.in);
int[] citations = new int[100];
String[] strs;
System.out.println("Please input the citation numbers:");
String line = scanner.nextLine();
strs = line.split(",");
for (int i = 0; i < strs.length; i++)
    citations[i] = Integer.parseInt(strs[i]);

(2)编写排序功能(冒泡排序)

for (int i = 0; i < number - 1; i++) {
    for (int j = 0; j < number - 1; j++) {
        if (citations[j] < citations[j + 1]) {
             int temp = citations[j + 1];
             citations[j + 1] = citations[j];
             citations[j] = temp;
        }
    }
}

(3)计算h-index

int hindex = 0;
for (int j = 0; j < number; j++) {
    if (citations[j] >= j + 1)
        hindex = j + 1;
    else
        break;
}
System.out.println("The h-index is: " + hindex);

接下来要输入不同的数组,进行手工测试。
上述编写完成后,git commit到v0.1All code in main()
(4)提取出单独的int hindex(int[] citations)函数
(5)提取出来形成单独的排序函数void sort(int[] array),git commit到v0.2 separate functions
(6) 从文本文件读入,存储于数组

健壮性处理

进行健壮性测试:

  • 输入空数组——抛出异常了
String line = new String();
line = scanner.nextLine();
while(line.length() == 0)
{
    System.out.println("Input empty, please re-input:");
    line = scanner.nextLine();
}

git commit到v0.3 avoid empty input string

  • 输入负值:
    策略:split之后,调用Integer.parseInt(strs[i])得到整数,检查其是否<0
  • 输入特殊值(非整数、非法字符等)
    策略1:比较笨的方法:逐个字符位置检查是否为数字
    策略2:与负值一起处理,用正则表达式检查分割后字符串是否匹配"[0-9]+"
    策略3:直接调用Integer.parseInt()或者Integer.valueOf().intValue(),若抛出异常,说明不合法,需要在捕获异常之后让用户重新输入

举例实现策略2:

//read input from keyboard
Scanner scanner = new
Scanner(System.in);
System.out.println("Please input the citation numbers:");     
int[] citations = new int[100];
String[] strs;
String line = new String();     

//loop, until user inputs legal string
while (true) {
    line = scanner.nextLine();
    //if the nput is empty
    if (line.length() == 0)
    {
       System.out.println("Input empty, please re-input:");
       continue;
    }     
    //check if each part is integer >= 0
    boolean legalNumbers = true;
    strs = line.split(",");
    for (int i = 0; i < strs.length; i++) {
       //if not,stop checking others and let user re-input
       if(! strs[i].matches("[0-9]+")) {
           System.out.println(strs[i] + " is illegal: ");
           legalNumbers = false;
           break;
       }
       //otherwise,store the integer into array
       citations[i] = Integer.parseInt(strs[i]); 
    }
    if (!legalNumbers)
       continue;
    else {
       //calculate h-index
       int hindex = hindex(citations);
       //output to console
       System.out.println("The h-index is: " + hindex);
       break;
    }
}

git commit到v0.4 avoid input string containing illegal characters

  • 需要注意的是,如果这里超过100个输入则会抛出异常,但是我们不能提前得知用户输入多少个
    策略:使用Java Collections, List, Set, Map, etc
//int[] citations = new int[5];
List<Integer> citations = new ArrayList<>();
//citations[i] = value;
citations.add(value);
int hindex = hindex(citations);
public static int hindex(List<Integer> citations) {
    //Integer[]
    array1 = (Integer[])citations.toArray();
    int[] array2 = new int[citations.size()];
    for(int i=0; i<citations.size(); i++)
       array2[i] = citations.get(i);
    // 冒泡排序
    sort(array2);
    // 计算h-index
    int hindex = 0;
    for (int j = 0; j < array2.length; j++) {
       if (array2[j] >= j + 1)
           hindex = j + 1;
       else
           break;
    }
    return hindex;
}

git commit到v0.5 use java collections instead of arrays

将计算功能与用户输入分离开来

从main中分离出来计算,main只处理调用(作为客户端程序)

public class HIndex3 {    
    private List<Integer> citations = new ArrayList<>(); 
    
    public HIndex3(String input) {
       if(input == null || input.length() == 0)
           throw new IllegalArgumentException("Empty");
       dealInput(input);
    }
    
    private void dealInput(String input) {   
       String[] strs = input.split(","); 
       for (int i = 0; i < strs.length; i++) {
           if(! strs[i].matches("[0-9]+")) 
              throw new IllegalArgumentException(strs[i] + " is illegal");
           citations.add(Integer.parseInt(strs[i]));
       }
    }
    
    public static void main(String[] args) {
       String[] inputs = new String[] {"1,0", "3,-2,4,8"};
       for(int i=0;i<inputs.length;i++) {
           HIndex3 h = new HIndex3(inputs[i]);
           System.out.println(h.calcHIndex());
       }
    }
    public int calcHIndex() {...}
    ...
}

git commit到v0.6 separate input with calculation
我们还可以通过静态函数进行调用

       for(int i=0;i<inputs.length;i++) {
           //HIndex3 h = new HIndex3(inputs[i]);
           System.out.println(HIndex3.calcHIndex(inputs[i]));
       }

git commit到v0.7 use static methods of a class

直接编写测试用例

打开Junit,演示测试用例如何书写、如何运行、正确和错误的执行结果
创建一个新的测试类HIndexTest.java
演示如何编写测试函数并启动执行、查看结果

  • 正确的、错误的

普通的用例如何测试:assertEquals
抛出异常如何测试?

  • 只看抛出异常的类型是否正确
    还要看抛出异常的消息是否正确

最好每个测试方法里只写一个测试用例
git commit到v0.8 design test cases manually

根据等价类和边界值思想,设计和编写测试用例

设计更完备的测试用例
Testing strategy:

  • 对输入的字符串进行等价类划分
  • 针对每一个划分结果来设计测试用例并撰写测试方法

git commit到v0.9 design test cases by equivalence partitioning

改造为OOP

构造Paper类,存储论文的题目、年份、期刊、引用数,封装起来,对Paper类进行功能扩展,包括增加引用数、减少引用数;
基于Paper类改造之前的HIndex类,将其改造为Author类,其中管理作者名字、发表论文清单,使用集合类表达一组Paper而不再用数组。
在Author类中增加功能:新增论文、修改某个论文的引用数、计算HIndex、toString(第一行打印出作者,后面每行是一篇论文[题目、引用数],最后是该作者的HIndex)。
写一个客户端(Author类的main函数,模拟使用Paper和Author类)

git commit到v1.0 oop

让Paper类具备在Collections中的排序功能:

  • 方案0:自行编写排序功能
  • 方案1:使用Comparator
  • 方案2:使用Comparable

实现方案2
git commit到v1.1 use comparator for sorting papers

重新编写和执行JUnit测试用例

对Paper类的各函数进行测试
对Author类的各函数进行测试

构造GUI

为用户开发一个GUI,让用户输入一组论文题目和引用数,计算出HIndex
使用JFrame,创建新GUI类

读取文本文件

在GUI上选择一个文件,从文本文件里读取数据,写入Paper对象和Collections

总结

本次习题课主要是为之前帮助Java没有了解的同学用Java编写项目。比如老师为同学们介绍了很多在编写Java项目中常用的方法或类,着重强调了与之前学过的C语言不同的地方,帮助同学们顺利完成实验一。

相关标签: 软件构造