第二周个人作业WordCount

Github地址

https://github.com/ChenSilence/WordCount

PSP表格

 

PSP2.1

PSP阶段

预估耗时

(分钟)

实际耗时

(分钟)

Planning

计划

 15

 15

· Estimate

· 估计这个任务需要多少时间

 30

 15

Development

开发

 360

 600

· Analysis

· 需求分析 (包括学习新技术)

60

60

· Design Spec

· 生成设计文档

 0

5

· Design Review

· 设计复审 (和同事审核设计文档)

 0

 0

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

 10

 10

· Design

· 具体设计

 20

 30

· Coding

· 具体编码

240

 420

· Code Review

· 代码复审

 40

 40

· Test

· 测试(自我测试,修改代码,提交修改)

 60

 100

Reporting

报告

 60

 80

· Test Report

· 测试报告

 40

 60

· Size Measurement

· 计算工作量

 10

20

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

 10

 20

 

合计

935

 1475

解题思路

 

  看到这个题目的时候,有点发怵,因为自己很久没有动手写Java代码了。并且看到需求说明里,要求按层次进行commit,因此我选择了先完成基础功能模块,即实现-w -l -c -o指令的解析,再逐步修改完成扩展功能模块即-s -a -e指令。

基本功能

  对于计数单词以及行数(-c -w -l)这些基础功能来看,我刚开始是打算按字符类型逐个硬编码分析计数字符总数,单词总数,以及行数。虽然该方法可行,但是代码量必定很大,而且由于需要每个字符都要进行嵌套的判断,必然导致识别速度慢。如果源文件非常大的话,那么执行速度将是不可接受的。进而我果断放弃了该思路,去查询相应的可以使用的java函数,以期方便快速的实现这些统计功能。

  对于-o心里大概有个数,只需要修改输出流路径,照这个思路去编码就可以了。

扩展功能

-s:递归查找后缀为.c的文件,将找到的所有路径保存到数组中,然后依次取出挨个执行命令。

-a:判断代码行,空行,注释行,同样由于效率的原因不得不排除了挨个判断字符的方法,在网上查询资料后了解到,可以使用正则表达式匹配的方法。因此又专门去学习了基本的正则表达式的写法,花费了很多的时间。

-e:停用词表。我的初步想法是在基本功能统计出单词的前提下,将输入文件与停用词表的单词逐个比对,计数匹配的数目,则总单词数目—匹配数目=考虑停用词后的单词数目。

程序设计实现过程

类的设计:

一共两个类,wordCount为主程序,testWC为测试类。

函数设计:

wordCount类中包含如下函数:

 

其中main函数无实际功能,只是生成实例调用entrance()函数。

然后再由entrance函数调用doPar进行参数解析,调用doOrder函数执行命令。

doOrder函数为代码的核心,根据参数处理结果,调用相应的子函数完成相应的功能。

 

testWC中只有一个test()函数,调用wordCount类中的entrance()函数对测试用例进行验证。

 

代码说明

首先展示解析args[ ]参数的函数doPar( ),

简单来说即只要包含有某命令(例如-w)时,就置相应的flag为1;若遇到特殊的如-e ,-o则将后面一个参数拷贝到对应的地址变量中。

 1     public void doPar(String[] args) {//处理参数
 2                     
 3                     for(int i = 0;i < args.length;i++) {
 4                     String nowPar = args[i];
 5                     
 6                     if (nowPar.length()==2) {//如果是命令
 7                         switch(nowPar.charAt(1)) {
 8                             case 'c':flag[0]=1;break;
 9                             case 'w':flag[1]=1;break;
10                             case 'l':flag[2]=1;break;
11                             case 'o':
12                                 flag[3]=1;
13                                 outFlag=true;
14                                 outFilePath =args[++i];//若识别出-o命令则将后一参数传给输出路径变量
15                                 break;
16                             case 's':
17                                 flag[4]=1;
18                                 break;
19                             case 'a':
20                                 flag[5]=1;
21                                 aFlag=true;
22                                 break;
23                             case 'e':
24                                 flag[6]=1;
25                                 stopFlag=true;
26                                 stopFilePath =args[++i];//若识别出-e命令则将后一参数传给停用词表的路径变量
27                                 break;
28                         
29                             default:break;
30                             }
31                     }
32                     
33                     else sourceFilePath = nowPar;//当参数为路径而前面又无命令符说明时,判定为输入文件路径
34                 }
35              }

 

下面是处理输出路径的实现,利用处理参数后置的outFlag值

 1                         if(!outFlag) {//不指定输出文件
 2                          fout = new FileWriter("bin/result.txt",true);
 3                         }
 4                         else //指定输出文件
 5                             fout = new FileWriter(outFilePath,true);
 6                         
 7                         try {
 8                             fout.write(result.toString());
 9                         } catch (IOException e) {
10                             e.printStackTrace();
11                         }
12                         fout.close();

统计字符函数

实现该函数时遇到的问题为,在windows环境下换行实际上“\r\n”两个字符,

而根据需求及所给例子来看,只应统计为一个,因此我采用了总字符减去\r字符数,代码如下:

 1             public int cCharNumber() {
 2                 String text = readFile(sourceFilePath);
 3                 int num_r=0;
 4                 for(int k=0;k<text.length();k++) {
 5                     if (text.charAt(k)=='\r') {
 6                         num_r++;
 7                     }
 8                 }
 9                 return text.length()-num_r;
10             }

统计单词函数

本函数中,我将是否有停用词命令加入到了判定中,即在该函数体的不同分支来实现是否需减去停用词数。

其中本函数调用了doStop函数返回与停用词表相同的单词数目,下一并列出。

 1             public int cWordNumber() {
 2                 String text = readFile(sourceFilePath);
 3                  String s[] = text.split("\\s+|,|\n");//split()里面是正则表达式
 4                  int wn = s.length;
 5                 if(stopFlag) {
 6                     return wn-doStop(s);
 7                 }
 8                 else
 9                     return s.length;
10             }
11             public int doStop(String[] s) {//与停用词表比对,统计出不该计算的单词数
12                 String stoplist = readFile(stopFilePath);
13                  String slist[] = stoplist.split(" +");
14                 int same=0;
15                 for(int i=0;i<s.length;i++) {
16                     for(int j=0;j<slist.length;j++) {
17                         if (s[i].equals(slist[j])){
18                             same++;
19                         }
20                     }
21                 }
22                 return same;
23             }

统计行数功能简单,代码略。

统计不同类型的行数

如前所述,判断复杂,因此我采用的是使用正则表达式来匹配。

设计出了注释行,空行的正则表达式,剩下的为代码行,具体如下:

 1             public String aCount() {//统计各行数
 2                 String all = null;
 3                 String text = readFile(sourceFilePath);
 4                 String s[] = text.split("\\r\\n");
 5                 int noteline,spaceline,codeline;
 6                 noteline=spaceline=codeline=0;
 7                  for(String tmp:s) {
 8                      if(Pattern.matches("\\s*.?\\s*//.*|//.*", tmp))//注释行可能是x//或者//xxx的形式
 9                      noteline++;
10                      else if(Pattern.matches("\\s*.?\\s*", tmp) || s==null)//空行可能有一个字符,或者本身为空串
11                     spaceline++;
12                      else 
13                     codeline++;//其他情况下为代码行
14                  }
15                 all=" 代码行/空行/注释行:"+codeline+"/"+spaceline+"/"+noteline;
16                 return all;
17             }

 

递归处理

 1             public static void find(String nowpath){
 2                 File f=new File(nowpath+"\\");//首先获得当前路径
 3                 File nowf=new File("");
 4                 File filelist[]=f.listFiles();//利用file的函数库中已有函数listfiles可方便的获得文件列表
 5                 if(filelist==null)  {System.out.println("目录为空"); return;}
 6                 for(int i=0;i<filelist.length;i++) {
 7                     nowf = filelist[i];
 8                     if (nowf.isFile() && nowf.getName().endsWith(".c")) {
 9 //                        if(!source.contains(nowf.getAbsolutePath()))
10                         source.addElement(nowf.getAbsolutePath());//循环判断后缀为.c文件的加入到路径集中
11                     } else if (nowf.isDirectory()) {
12                         find(nowf.getAbsolutePath());//递归
13                     }
14 
15                 }
16        }

 

测试设计过程:

我首先考虑的是达到白盒测试的语句覆盖,即设计出的测试用例覆盖了所有语句。然后又针对条件分支进行了设计,

我自己私认为如下设计的12个测试用例可以满足要求。

  1. "-c test4.c",

   测试最基本的统计字符功能
  2.   "-w  test4.c",

   测试基本的统计单词功能
  3.  "-l  test4.c",

   测试行数统计
      4."-c -w -l test4.c",

   同时满足三个条件
      5."-l -w test5.c -o result5.txt",

   测试指定输出路径
      6."-l -a test6.c -o result6.txt",

   测试统计复杂的行数据,且统计所有行
    7.  "–a test4.c",

   统计复杂的行数据
     8.  "–w test5.c –e stop.txt",

  测试停用词表
     9. "–w test6.c –e stop.txt -o result6.txt",

  同时满足停用词表且指定输出路径
      10."-w -l -s *.c",

  测试递归
     11. "-l -w -s D:\\java-oxygen\\eclipse-workspace\\WordCount\\*.c",

  测试指定路径的递归
     12 "-l -w -c -s -a -e stop.txt  D:\\java-oxygen\\eclipse-workspace\\WordCount\\*.c -o result7.txt"

  对最复杂的路径进行测试

  

参考文献链接

http://blog.csdn.net/chivalrousli/article/details/51146951   java 追加内容到文件末尾的几种常用方法
https://www.cnblogs.com/newcaoguo/p/6224071.html   java中File类的getPath(),getAbsolutePath(),getCanonicalPath()区别
http://blog.csdn.net/centforever/article/details/47311891   Java Vector遍历的五种方法
https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000  廖雪峰git教程
http://www.cnblogs.com/ningjing-zhiyuan/p/8563562.html   第2周个人作业:WordCount

转载于:https://www.cnblogs.com/bokeyuanchen/p/8608812.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值