软件构造感想2

对给定的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语言不同的地方,帮助同学们顺利完成实验一。

发布了2 篇原创文章 · 获赞 0 · 访问量 14

猜你喜欢

转载自blog.csdn.net/ruiye117/article/details/105014050