软件工程 作业三

软件工程 作业三


1.要求地址


2.PSP表格

PSP2.1 个人开发流程 预估耗费时间(分钟) 实际耗费时间(分钟)
Planning 计划 5 3
· Estimate 明确需求和其他相关因素,估计每个阶段的时间成本 5 3
Development 开发 274 308
· Analysis 需求分析 (包括学习新技术) 60 60
· Design Spec 生成设计文档 5 2
· Design Review 设计复审 4 2
· Coding Standard 代码规范 5 5
· Design 具体设计 10 20
· Coding 具体编码 120 180
· Code Review 代码复审 10 9
· Test 测试(自我测试,修改代码,提交修改) 60 30
Reporting 报告 40 65
· 测试报告 30 60
· 计算工作量 5 2
· 并提出过程改进计划 3 3

3.解题思路描述

这次的项目是建立在上一次作业的项目的基础上,在功能上,主要有两个新增的地方:

  • 词组统计:能统计文件夹中指定长度的词组的词频
  • 自定义输出:能输出用户指定的前n多的单词与其数量

然后在设计上则是新增了GUI界面

词组统计的话,是使用了多重循环,分层进行判断,在存储方面也是使用了Map进行存储。

自定义输出的解题思路:戳这里戳这里戳这里

GUI界面使用了netbeans以及web来实现。

我对于GUI界面是使用了netBeans来实现,使用了文本框控件,菜单控件等来实现处理文件以及字符处理,通过给不同按钮添加相应事件,以此来实现不同的功能。

web界面的解题解题思路:戳这里戳这里戳这里


4.设计实现过程

一、相关类设计

  • WordDeal类,用于存放统计字符数、行数、单词数、词频等方法。
  • FileDeal类作为文件处理类,用于读取文件内容以及写入文件。
  • Test类,用于进行单元测试。​

二、相关函数设计

  1. FIleDeal类中的方法
    • FileToString方法实现读取一个文件,并且返回文件内容,保存在一个字符串中。
    • WriteToFile方法实现把统计结果写入指定文件。
  2. WordDeal类中的方法
    • getCharCount()方法实现统计字符数。
    • getLineCount()方法实现计算行数。
    • getWordCount()方法实现计算单词数。
    • getWordFreq()方法实现统计每一个单词的词频。
    • sortMap()方法实现对Map中的数据进行排序,先按词频数后按字典顺序。
    • ListToArray()方法实现取出词频数前十的数据。
    • getWordGroupFreq(int num)方法用于统计长度为num的词组
  3. ScDeal类中的方法
    • 初始化函数scDeal()
    • 判断输入函数judge()
    • ideal()是-i的处理函数
    • mdeal()是-m的处理函数
    • ndeal()是-n的处理函数
    • odeal()输出到文件函数
    •  judge()判断各自输入然后调用不同的处理函数

三、GUI界面设计

  1. netBeans版本:
    • wGUI包下的Main类,使用netBeans设计其相关界面布局等。
  2. Web版本:
    • Main.jsp页面,用于基本界面的设计实现
    • show.jsp页面,用于表单提交处理界面的实现

5.代码说明

1.getWordGroupFreq(int num)函数

这个函数实现了统计指定长度的词组的词频信息,通过传入词组长度,然后遍历整个文件内容,先判断单词,再进行词组的判断。最后的存储还是使用Map来进行存储,以便于统计输出。

public Map getWordGroupFreq(int num) // 统计词组词频(单词:以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。)
{
    wordGroupFreq = new HashMap<String, Integer>();
    String t = text;

    String[] spWord = t.split("\\s+"); // 对字符串进行分词操作
    for (int i = 0; i < spWord.length - num + 1; i++) {
        String wordG = "";
        int isWG = 1;
        for (int j = i; j < i + num; j++) {
            if (spWord[j].length() < 4) { // 判断是否是单词,若不是,则直接不用考虑这个词组
                isWG = 0;
                break;
            } else {

                int flag = 1; // 判断字符串的前四位是否是英文字母
                char c;

                for (int k = 0; k < 4; k++) {
                    c = spWord[j].charAt(k);

                    if (!(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) {
                        flag = 0;
                    }
                }
                if (flag == 0) {
                    isWG = 0;
                    break;
                } else {
                    wordG = wordG + spWord[j] + " ";
                }
            }
        }

        if (isWG == 1 && wordG.trim().length() != 0) {
            if (wordGroupFreq.get(wordG.trim()) == null) { // 判断之前Map中是否出现过该词组
                wordGroupFreq.put(wordG.trim(), 1);
            } else {
                wordGroupFreq.put(wordG.trim(), wordGroupFreq.get(wordG.trim()) + 1);
            }

        }

    }

    return wordGroupFreq;
}

2.GUI界面主要函数

  1. 打开文件

    该函数用于实现菜单控件中打开文件的功能实现。通过选取文件,将文件内容显示到相应的地方。

        private void openFileActionPerformed(java.awt.event.ActionEvent evt) {                                         
            f = new Frame("my window");// 创建窗体对象
            f.setBounds(300, 100, 650, 600);// 设置窗体位置和大小
            open = new FileDialog(f, "打开", FileDialog.LOAD);
    
            open.setVisible(true);//显示打开文件对话框
    
            String dirpath = open.getDirectory();//获取打开文件路径并保存到字符串中。
            String fileName = open.getFile();//获取打开文件名称并保存到字符串中
    
            if (dirpath == null || fileName == null)//判断路径和文件是否为空
            {
                return;
            } else {
                text.setText(null);//文件不为空,清空原来文件内容。
            }
            File file = new File(dirpath, fileName);//创建新的路径和名称
    
            try {
                //BufferedReader bufr = new BufferedReader(new FileReader(file));//尝试从文件中读东西
                BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream(file), "gb2312"));
                String line = null;//变量字符串初始化为空
                while ((line = bufr.readLine()) != null) {
                    text.append(line + "\r\n");//显示每一行内容
                }
                bufr.close();//关闭文件
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }                                        
  2. 保存文件

    扫描二维码关注公众号,回复: 3464238 查看本文章

    该函数用于将结果框中的内容保存为文件。

       private void saveFileActionPerformed(java.awt.event.ActionEvent evt) {           
            save = new FileDialog(f, "保存", FileDialog.SAVE);
    
            save.setVisible(true);//显示保存文件对话框
            String dirpath = save.getDirectory();//获取保存文件路径并保存到字符串中。
            String fileName = save.getFile();////获取打保存文件名称并保存到字符串中
    
            if (dirpath == null || fileName == null)//判断路径和文件是否为空
            {
                return;//空操作
            } else {
                file = new File(dirpath, fileName);//文件不为空,新建一个路径和名称
            }
            try {
                BufferedWriter bw = new BufferedWriter(new FileWriter(file));
    
                String text = result.getText();//获取文本内容
                bw.write(text);//将获取文本内容写入到字符输出流
    
                bw.close();//关闭文件
            } catch (IOException e1) {
                //抛出IO异常
                e1.printStackTrace();
            }
        }      
  3. 功能函数的调用

    这一类的方法是根据点击的不同按钮,对应实现不同的方法,并将结果进行展示。

        private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
            // TODO add your handling code here:
            String t = text.getText();
            WordDeal wd = new WordDeal(t);
            // 调用类中的方法获取相应的数值
            int charNum = wd.getCharCount();
            int wordCount = wd.getWordCount();
            int ValidLine = wd.getLineCount();
            Map<String, Integer> wordFreq = wd.getWordFreq();
    
            List sortMap = wd.sortMap(wordFreq);
    
            String[] wFreq = wd.ListToArray(sortMap);
    
            String w = "字符总数:" + charNum + "\r\n" + "单词总数" + wordCount + "\r\n" + "有效行数" + ValidLine + "\r\n词频统计:\r\n";
            for (int i = 0; i < wFreq.length; i++) {
                w = w + wFreq[i] + "\r\n";
            }
            result.setText(w);   //写入到相应的控件之中
    
    
        }        

6.回归测试

  1. 对原有函数的回归测试

    package junitTest;
    
    import static org.junit.Assert.*;
    import java.io.IOException;
    import java.util.*;
    import org.junit.Before;
    import org.junit.Test;
    import wCount.*;
    
    public class WordDealTest {
    
     @Before
     public void setUp() throws Exception {
    
     }
    
     @Test
     public void testGetCharCount() throws IOException {//统计字符数量测试
         FileDeal fd = new FileDeal();
         String text1 = fd.FileToString("text/text1.txt");   
         String text2 = fd.FileToString("text/text2.txt");   
         String text3 = fd.FileToString("text/text3.txt");
         String text4 = fd.FileToString("text/text4.txt");
    
    
         WordDeal wd1 = new WordDeal(text1);
         WordDeal wd2 = new WordDeal(text2);
         WordDeal wd3 = new WordDeal(text3);
         WordDeal wd4 = new WordDeal(text4);
    
         int cn1 = wd1.getCharCount();
         int cn2 = wd2.getCharCount();
         int cn3 = wd3.getCharCount();
         int cn4 = wd4.getCharCount();
    
         assertEquals(0, cn1);
         assertEquals(0, cn2);
         assertEquals(80, cn3);
         assertEquals(73, cn4);
    
     }
    
     @Test
     public void testGetWordCount() throws IOException {//统计单词数量测试
         FileDeal fd = new FileDeal();
         String text1 = fd.FileToString("text/text1.txt");
         String text2 = fd.FileToString("text/text4.txt");
    
         WordDeal wd1 = new WordDeal(text1);
         WordDeal wd2 = new WordDeal(text2);
    
         int wn1 = wd1.getWordCount();
         int wn2 = wd2.getWordCount();
    
         assertEquals(0, wn1);
         assertEquals(3, wn2);
     }
    
     @Test
     public void testGetWordFreq() throws IOException {//统计词频测试
         Map<String,Integer> ans1 = new HashMap<String,Integer>();
         Map<String,Integer> ans2 = new HashMap<String,Integer>();
    
         ans2.put("coverage", 1);
         ans2.put("yizhishuijiao", 2);
    
         FileDeal fd = new FileDeal();
         String text1 = fd.FileToString("text/text1.txt");
         String text2 = fd.FileToString("text/text4.txt");
    
         WordDeal wd1 = new WordDeal(text1);
         WordDeal wd2 = new WordDeal(text2);
    
         Map<String,Integer> wf1 = wd1.getWordFreq();
         Map<String,Integer> wf2 = wd2.getWordFreq();
    
         assertEquals(ans1, wf1);
         assertEquals(ans2, wf2);
     }
    
     @Test
     public void testSortMap() throws IOException {//词频排序测试
    
    
         FileDeal fd = new FileDeal();
         String text1 = fd.FileToString("text/text1.txt");
         String text2 = fd.FileToString("text/text4.txt");
    
         WordDeal wd1 = new WordDeal(text1);
         WordDeal wd2 = new WordDeal(text2);
    
         Map<String,Integer> wf1 = wd1.getWordFreq();
         Map<String,Integer> wf2 = wd2.getWordFreq();
    
         List lis1 = wd1.sortMap(wf1);
         List lis2 = wd2.sortMap(wf2);
    
         //assertEquals(ans1, wf1);
         //assertEquals(ans2, wf2);
     }
    
     @Test
     public void testGetLineCount() throws IOException {//统计有效行数测试
         FileDeal fd = new FileDeal();
         String text1 = fd.FileToString("text/text1.txt");
         String text2 = fd.FileToString("text/text4.txt");
    
         WordDeal wd1 = new WordDeal(text1);
         WordDeal wd2 = new WordDeal(text2);
    
         int wn1 = wd1.getLineCount();
         int wn2 = wd2.getLineCount();
    
         assertEquals(0, wn1);
         assertEquals(4, wn2);
     }
    
     @Test
     public void testListToArray() throws IOException {
    
    
         FileDeal fd = new FileDeal();
         String text1 = fd.FileToString("text/text1.txt");
         String text2 = fd.FileToString("text/text4.txt");
         String text3 = fd.FileToString("text/text5.txt");
    
         WordDeal wd1 = new WordDeal(text1);
         WordDeal wd2 = new WordDeal(text2);
         WordDeal wd3 = new WordDeal(text3);
    
         Map<String,Integer> wf1 = wd1.getWordFreq();
         Map<String,Integer> wf2 = wd2.getWordFreq();
         Map<String,Integer> wf3 = wd3.getWordFreq();
    
         List lis1 = wd1.sortMap(wf1);
         List lis2 = wd2.sortMap(wf2);
         List lis3 = wd3.sortMap(wf3);
    
         String[] s1 = wd1.ListToArray(lis1);
         String[] s2 = wd2.ListToArray(lis2);
         String[] s3 = wd3.ListToArray(lis3);
     }
    
    }

    测试结果:

  2. 对新增函数的测试

    测试用例:

    测试代码:

     @Test
     public void testGetWordGroupFreq() throws IOException {//统计词组测试
    
         FileDeal fd = new FileDeal();
         String text6 = fd.FileToString("text/text6.txt");
         WordDeal wd6 = new WordDeal(text6);
         Map<String,Integer> wf6 = wd6.getWordGroupFreq(3);  
     }

    测试结果:


7.单元测试

  1. 对命令行版本项目的单元测试






  2. 对web版本项目的单元测试







  1. 对netBeans版本项目的单元测试








    ------

8.效能测试

  1. 对命令行版本项目的效能测试

  2. 对web版本项目的效能测试



  1. 对netBeans版本项目的效能测试



9.结对心得

这次的结对编程是针对一个项目进行的改进,因为这次的要求,命令行输入和GUI界面的实现是两个相对独立的版本,所以经过讨论以后,我们的分工基本还是由我写完新增函数以后,由每个人来实现一个版本,相对来说除了在调用函数方面,其他部分还是比较独立的,所以其实并没有很多结对的感觉,但是在最开始讨论的时候,每个人都还没有很清晰的认识这个过程,导致对这个项目各有各的看法,然后讨论的效率还是比较低,花了很长时间才得到的统一。所以这次编程并没有很多的感受到1+1>2的效果


猜你喜欢

转载自www.cnblogs.com/cxf1404445126/p/9750858.html