• 结对作业——WordCount进阶版


    结对作业——WordCount进阶版

    标签(空格分隔): 软件工程


    Task1:Fork仓库的码云地址

    Task2:PSP表格

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

    Task3:解题思路描述

    题目的需求分析:

    WordCount 结对项目在个人项目的基础上,增加新的功能如下:

    • 词组统计:能统计文件夹中指定长度的词组的词频
    • 自定义输出:能输出用户指定的前n多的单词与其数量
      为了实现上述软件,我们首先要在个人项目基础上增量改进,实现一个Core模块,并基于Core模块实现在命令行测试程序中支持下述命令行参数(原有命令行参数不变)
    • -i 参数设定读入的文件路径
      wordCount.exe -i [file]

    • -m 参数设定统计的词组长度
      wordCount.exe -m [number]

    • -n参数设定输出的单词数量
      wordCount.exe -n [number]

    • -o参数设定生成文件的存储路径
      wordCount.exe -o output.txt


    思路分析:

    这道题是继续上次个人作业的,比起之前多了两个功能,同时加上了前端界面的设计。因为是结对编程,首先我们在代码的确定上做了一些交谈。

    • 我的代码在功能实现的基础上,对于文件类的读取比较全面,有考虑到打开or写入的文件为空文件,但是在其他特殊符号的处理上没有结对小伙伴的全面。
    • 而她的是在特殊符号上做的全面,但是没有考虑到打开空文件的情况

    经过一些讨论,我们决定在基础上采用她的代码,进行新功能的添加。她来负责添加新功能,实现用命令行来执行相关操作,我来负责单元测试,用netBean来实现GUI界面。

    Task4:设计实现过程

    一、相关类的设计

      针对这个要求,得到一个主函数,两个类,其中:

    • Count类:进行字符数量、行数、单词数、词频的统计。
    • File类:进行文件内容的读取,以及处理结果的写入。
    • read类:将string类型的字符串转换成ArrayList类型。
    • Main类:结合实际情况,创建以上两种对象,进行方法的调用,实现题目要求。
    • CountTest:用于单元测试。

    二、相关函数的设计

    Count:

    1. count.CountChars(); //字符数统计
    2. count.CountWords();//单词数统计
    3. count.CountLine();//有效行统计
    4. count.WordTop(n,CountWords);//单词频率统计,统计数量排名前n的单词
    5. count.CountPhrase(m);//统计长度为m词组

    File:

    1. file.readfile(path);//读出文件内容变成ArrayList格式类型
    2. file.writefile(save, CountChars, CountWords, CountLine, wordtop, CountPhrase);//按照要求和给出的路径写入指定文件

    read:

    1. re.readfile(line);//将string类型的字符串转换成ArrayList类型

    三、GUI界面设计

    使用netBeans设计其相关界面布局,具有打开指定文件,保存为指定文件,并可以更改参数m和参数n的值进行统计。页面样式如下:


    Task5:代码说明

    1. Read类中readfile(String line)函数

      该函数用于将string类型的字符串转换成ArrayList类型,由于在netBeans的文本框类型中的getText()得到的是整个字符串,而我的队友写的处理字符的count类是针对ArrayList类型,所以需要进行转换才可以嵌套

    public class Read {	//将string类型的字符串转换成ArrayList<String>类型
        public ArrayList<String> readfile(String line){
    	ArrayList<String> arrylist=new ArrayList<>();
    	String[] everyword = line.split("
    ");//用空格作为分割
        System.out.println("everyword.length_"+everyword.length);
        String str;
           for(int j=0;j<everyword.length;j++){
               arrylist.add(everyword[j]);//添加到ArrayList<String>类型数组
           }
            
        System.out.println(arrylist);
         
                    
    		return arrylist;
    	}
    }
    

    2.GUI界面主要函数

    • 触发按钮功能
      这一类的方法是,当用户设置好内容点击开始统计按钮后,所绑定的函数进行调用,并在文本框中进行展示
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
    		// TODO add your handling code here:
    		int n1 = (int) n.getValue();//获取微调器的内容
    		int m1 = (int) m.getValue();//获取微调器的内容
    		System.out.println(n1);
    		System.out.println(m1);
    		String line = jTextArea2.getText();//获取文本区域的内容
    		System.out.println("line_" + line);
    		// line = line.replace('
    ',' ');
    		Read re = new Read();
    		ArrayList<String> arrylist = new ArrayList<>();
    		arrylist = re.readfile(line);
    
    		System.out.println(arrylist + "!!!!!!!!!!");
    
    		Count count = new Count(arrylist);
    		int CountChars = count.CountChars();
    		int CountWords = count.CountWords();
    		int CountLine = count.CountLine();
    		System.out.println(CountChars);
    		System.out.println(CountWords);
    		System.out.println(CountLine);
    		ArrayList<Entry<String, Integer>> wordtop = count.WordTop(n1, CountWords);
    		Map<String, Integer> CountPhrase = count.CountPhrase(m1);
    
    		String total;
    		String str1 = "characters:" + CountChars;
    		String str2 = "words:" + CountWords;
    		String str3 = "lines:" + CountLine;
    
    		total = str1 + "
    " + str2 + "
    " + str3 + "
    ";
    
    		for (int i = 0; i < wordtop.size(); i++) {//遍历输出
    			Map.Entry<String, Integer> e = wordtop.get(i);
    			total = total + e.getKey() + ":" + e.getValue() + "
    ";
    		}
    		for (Entry<String, Integer> Phrase : CountPhrase.entrySet()) {//遍历输出
    			total = total + Phrase.getKey() + ":" + Phrase.getValue() + "
    ";
    		}
    		jTextArea1.setText(total);//将字符串写入到文本区域中
    
        }//GEN-LAST:event_jButton2ActionPerformed
    
    • 打开文件功能
      这个用于设置打开文件时的选择框。
     private void jRadioButtonMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonMenuItem1ActionPerformed
            // TODO add your handling code here:
            
            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 {
                jTextArea2.setText(null);//文件不为空,清空原来文件内容。
            }
            java.io.File file = new java.io.File(dirpath, fileName);//创建新的路径和名称
    
            try {
                BufferedReader bufr = new BufferedReader(new FileReader(file));//尝试从文件中读东西
                String line = null;//变量字符串初始化为空
                while ((line = bufr.readLine()) != null) {
                    jTextArea2.append(line + "
    ");//显示每一行内容
                }
                bufr.close();//关闭文件
            } catch (FileNotFoundException e1) {
                // 抛出文件路径找不到异常
                e1.printStackTrace();
            } catch (IOException e1) {
                // 抛出IO异常
                e1.printStackTrace();
            }
        }//GEN-LAST:event_jRadioButtonMenuItem1ActionPerformed
    
    
    
    • 保存文件功能
      这个用于将运行结果的内容保存到指定地点的指定文件中。
    private void jRadioButtonMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonMenuItem2ActionPerformed
            // TODO add your handling code here:
            save = new FileDialog(f, "保存", FileDialog.SAVE);
            if (file == null) {
                save.setVisible(true);//显示保存文件对话框
                String dirpath = save.getDirectory();//获取保存文件路径并保存到字符串中。
                String fileName = save.getFile();////获取打保存文件名称并保存到字符串中
    
                if (dirpath == null || fileName == null)//判断路径和文件是否为空
                {
                    return;//空操作
                } else {
                    file = new java.io.File(dirpath, fileName);//文件不为空,新建一个路径和名称
                }
            }
            try {
                BufferedWriter bw = new BufferedWriter(new FileWriter(file));
    
                String text = jTextArea1.getText();//获取文本内容
                bw.write(text);//将获取文本内容写入到字符输出流
    
                bw.close();//关闭文件
            } catch (IOException e1) {
                //抛出IO异常
                e1.printStackTrace();
            }
        }//GEN-LAST:event_jRadioButtonMenuItem2ActionPerformed
    

    Task6:单元测试

      根据以上函数,设置了一些测试点,尽可能罗列出各种情况:

    • 字符数为空,但有其他换行等符号
    • 中文和英文混合文件
    • 完全的英文文件
    • 完全的英文文件,大小写混合
    • 完全的英文文件,无合法单词

    对应设置的文件为:

    • test1:完全的空文件,但是有回车空格等符号
    • test2:中文和英文混合文件
    • test3:纯英文文件,完全小写
    • test4:纯英文文件,大小写混合
    • test5:英文、数字、特殊符号混合

    测试代码:

    class CountTest {
    
    	String file1 = "D:\soft-ware\PersonalProject-Java\201621123037qinyu\WordCount_2\test1.txt";
    	String file2 = "D:\soft-ware\PersonalProject-Java\201621123037qinyu\WordCount_2\test2.txt";
    	String file3 = "D:\soft-ware\PersonalProject-Java\201621123037qinyu\WordCount_2\test3.txt";
    	String file4 = "D:\soft-ware\PersonalProject-Java\201621123037qinyu\WordCount_2\test4.txt";
    	String file5 = "D:\soft-ware\PersonalProject-Java\201621123037qinyu\WordCount_2\test5.txt";
    	
    	
    	@BeforeEach
    	void setUp() throws Exception {
    	}
    
    	
    	@Test
    	void testCountChars() throws IOException {
    		File file=new File();
    		ArrayList<String> line1=new ArrayList<>();
    		ArrayList<String> line2=new ArrayList<>();
    		ArrayList<String> line3=new ArrayList<>();
    		ArrayList<String> line4=new ArrayList<>();
    		
    		line1=file.readfile(file1);
    		line2=file.readfile(file2);
    		line3=file.readfile(file3);
    		line4=file.readfile(file4);
    		
    		Count count1=new Count(line1);
    		Count count2=new Count(line2);
    		Count count3=new Count(line3);
    		Count count4=new Count(line4);
    		
    		int CountChars1=count1.CountChars();
    		int CountChars2=count2.CountChars();
    		int CountChars3=count3.CountChars();
    		int CountChars4=count4.CountChars();
    		
    	//	assertEquals(CountChars1,0);
    		assertEquals(CountChars2,24);
    		assertEquals(CountChars3,56);
    		assertEquals(CountChars4,200);
    		
    	}
    
    	@Test
    	void testCountWords() throws IOException {
    		File file=new File();
    		ArrayList<String> line1=new ArrayList<>();
    		ArrayList<String> line2=new ArrayList<>();
    		ArrayList<String> line3=new ArrayList<>();
    		ArrayList<String> line4=new ArrayList<>();
    		
    		line1=file.readfile(file1);
    		line2=file.readfile(file2);
    		line3=file.readfile(file3);
    		line4=file.readfile(file4);
    		
    		Count count1=new Count(line1);
    		Count count2=new Count(line2);
    		Count count3=new Count(line3);
    		Count count4=new Count(line4);
    		
    		int CountWords1=count1.CountWords();
    		int CountWords2=count2.CountWords();
    		int CountWords3=count3.CountWords();
    		int CountWords4=count4.CountWords();
    		
    		//assertEquals(CountWords1,5);
    		assertEquals(CountWords2,1);
    		assertEquals(CountWords3,9);
    		assertEquals(CountWords4,27);
    	}
    
    	@Test
    	void testCountLine() throws IOException {
    		File file=new File();
    		ArrayList<String> line1=new ArrayList<>();
    		ArrayList<String> line2=new ArrayList<>();
    		ArrayList<String> line3=new ArrayList<>();
    		ArrayList<String> line4=new ArrayList<>();
    		
    		line1=file.readfile(file1);
    		line2=file.readfile(file2);
    		line3=file.readfile(file3);
    		line4=file.readfile(file4);
    		
    		Count count1=new Count(line1);
    		Count count2=new Count(line2);
    		Count count3=new Count(line3);
    		Count count4=new Count(line4);
    		
    		int CountLine1=count1.CountLine();
    		int CountLine2=count2.CountLine();
    		int CountLine3=count3.CountLine();
    		int CountLine4=count4.CountLine();
    		
    		//assertEquals(CountLine1,5);
    		assertEquals(CountLine2,6);
    		assertEquals(CountLine3,4);
    		assertEquals(CountLine4,12);
    	}
    
    	@Test
    	void testWordTop() throws IOException {
    		/*File file=new File();
    		ArrayList<String> line=new ArrayList<>();
    		int n = 10;//-n参数设定输出的单词数量
    		line=file.readfile(file1);
    		
    		Count count=new Count(line);
    		int CountWords=count.CountWords();
    		
    		int WordTop=count.WordTop(n,CountWords).size();
    		
    		assertEquals(WordTop,10);*/
    		
    	}
    
    	@Test
    	void testCountPhrase() throws IOException {
    
    	
    		
    /*
    		File file=new File();		
    		ArrayList<String> line=new ArrayList<>();
    		line=file.readfile(file4);
    		//System.out.println(line);
    		Count count=new Count(line);
    		Map<String,Integer> CountPhrase=count.CountPhrase(4);*/
    		
    		File file=new File();		
    		ArrayList<String> line=new ArrayList<>();
    		line=file.readfile(file4);
    		Count count=new Count(line);
    		int CountChars=count.CountChars();
    		int CountWords=count.CountWords();
    		int CountLine=count.CountLine();
    		//ArrayList<Entry<String, Integer>> wordtop=count.WordTop(n,CountWords);
    		Map<String,Integer> CountPhrase=count.CountPhrase(4);
    		
    		/*Map<String,Integer> w1 = new HashMap<String,Integer>();
    		Map<String,Integer> w2 = new HashMap<String,Integer>();*/
    		Map<String,Integer> w3 = new HashMap<String,Integer>();
    	//	Map<String,Integer> w4 = new HashMap<String,Integer>();
    	
    		w3.put("dreams will come true", 1);
    		w3.put("live through your pain", 1);
    		w3.put("trying times will pass", 1);
    		w3.put("your dreams will come", 1);
    		
    		System.out.println("CountPhrase");
    		System.out.println(CountPhrase);
    		
    		System.out.println("w3");
    		System.out.println(w3);
    		
    		assertEquals(CountPhrase, w3);
    		
    	}
    
    }
    
    

    测试结果:

    错误问题

    在测试testCountPhrase()中,运用如下代码测试结果一直出错,输出的部分也可以看出CountPhrase中的内容一直为空,但是在之前写好的main函数中同样调用却不会出问题。

    测试代码:

    File file=new File();		
    		ArrayList<String> line=new ArrayList<>();
    		line=file.readfile(file4);
    		//System.out.println(line);
    		Count count=new Count(line);
    		Map<String,Integer> CountPhrase=count.CountPhrase(4);
    

    输出结果:

    CountPhrase
    {}
    w3
    {dreams will come true=1, live through your pain=1, trying times will pass=1, your dreams will come=1}
    

    解决过程

    经过反复输出核对代码,发现在count类中有设置一个Map<String,Integer> map=new HashMap<String,Integer>();,并且这个参数在以下两个方法中都有被调用。

    故,测试代码:

    File file=new File();		
    		ArrayList<String> line=new ArrayList<>();
    		line=file.readfile(file4);
    		Count count=new Count(line);
    		int CountChars=count.CountChars();
    		int CountWords=count.CountWords();
    		int CountLine=count.CountLine();
    		Map<String,Integer> CountPhrase=count.CountPhrase(4);
    
        
    

    测试结果:

    分值覆盖率截图:

    Task7:对netBeans进行文件内容测试截图

    运行结果:

    test1.txt




    test2.txt




    test3.txt




    test4.txt




    test5.txt



    ![](https://img2018.cnblogs.com/blog/1099326/201810/1099326-20181009183435645-509644937.png)


    Task8:效能分析


    Task9:心得体会

      在这次实验中,双人结对编程将编写代码从单人奋斗变成了一起奋斗,这中间我们有很多次沟通交流,很多次选择实现方法,还有任务的分配。通过这次实验我理解了书上写的编写代码的规范,如果编写代码规范上不够严格处理,那么对于结队的队友是一个极大的考验。。。花费在理解代码上的时间会更多。不过总的来说还是完成了任务,虽然因为假期我们回家导致两个人分割异地,但是我们还是坚持在QQ上聊天以及通视频,完成两个程序员之间的亲密交流。总的来说,两人合作的话缺点在于如果不能及时沟通,可能会导致浪费时间的不必要做功,但是可以制定更加完备的方案,考虑问题更加全面,如果再来一次还是结队能学到对方的一些小诀窍,做事上的思维宽度可以拓宽。

  • 相关阅读:
    LinkLabel控件使用
    读取mysql代码片段
    设置点风格
    C# List 用法
    图片焦点图切换效果
    dreamweaver 泛泛之谈
    js 之for..in、表单及事件触发
    实现省份查询 功能
    input类主要是
    js (1)
  • 原文地址:https://www.cnblogs.com/qin-yu/p/9756969.html
Copyright © 2020-2023  润新知