word count 项目总结

1、github地址html

https://github.com/hyt1022/wordcountjava

 

2、PSP表格git

PSP2.1github

PSP阶段编程

预估耗时数组

(分钟)eclipse

实际耗时ide

(分钟)函数

Planning学习

计划

30

30

· Estimate

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

30

30

Development

开发

840

1200

· Analysis

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

60

60

· Design Spec

· 生成设计文档

60

60

· Design Review

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

30

30

· Coding Standard

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

30

30

· Design

· 具体设计

120

120

· Coding

· 具体编码

360

600

· Code Review

· 代码复审

60

60

· Test

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

120

240

Reporting

报告

160

240

· Test Report

· 测试报告

100

150

· Size Measurement

· 计算工做量

30

30

· Postmortem & Process Improvement Plan

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

30

60

 

合计

1030

1470

 

3、解题思路介绍

 拿到题目后。首先对程序的准备进行了思考。

此次用Java进行编程,选用的编译器是Myeclipse10,配置的jdk版本是   。由于有一段时间没有写java,稍微有些生疏。所以查阅了大二时面向对象程序设计【1】。这本书对于java的基本语法和经常使用类进行了总结和用法指导,深刻浅出。

后面考虑到要生成exe文件,所以在网上查阅了如何将java项目打包生成exe文件【2】。

考虑到要将本地项目上传到github,在网上查阅了用命令行上传github的方法。【3】

再对程序的实现进行分析。

看到程序很容易就想到去年编译技术课程。此次的程序也能够沿用编译技术的部分的思想。

对于基础功能。最直接的想法是,经过将须要分析的* .c文件读入。用一个字符数组进行存储。对数组从到头尾扫一遍,在扫的过程当中,分析统计文件的字符,单词数,行数等。

对于拓展功能。在基础功能的基础上,在扫的过程当中考虑更多的因素。对于停用词表,现将词表读入文件,分红每个停用词,存入一个动态的字符数组。在扫待测数组时,将读到的每一个单词与停用词表进行比较,统计停用词的个数。统计代码行,空行,数据行的基本思路也和基础功能的一致。可是须要考虑更多的状态,以分析判断此行到底属于哪种类型。

对于基本输入输出。输入方式经过main函数自带的参数,分析args[],来判断输入的指令。输出则经过输入的文件名,将输出结果写入txt文件。

 

4、代码说明

public void analyse(String fileName,String stoplistFile,boolean f5) { Readfile(fileName); if(f5) { ReadStoplist(stoplistFile); } file = fileName; String tempword; String tep = new String(tempchars); int flag = 0;//判断上一个字符的标志,用来推断单词数是否增长;进入单词分隔符则为0,进入可显示字符则为1
    while(tempchars[p] != '\0') { if(tempchars[p] == '\n') { flag = 0; l++; p++; } else if(tempchars[p] == '\r') { flag = 0; p++; } else if(tempchars[p] == '\t') { flag = 0; p++; } else if(tempchars[p] == ' ') { flag = 0; p++; } else if(tempchars[p] == ',') { flag = 0; p++; } else//若是是可显示的字符
 { if(flag == 0)//若是上一个是单词分隔符则单词数加一
 { w++; if(f5)//若是有停用词表则进行分析
 { int a=p; while(tempchars[p] != '\n'&&tempchars[p] != '\r'&&tempchars[p] != '\t'&& tempchars[p] != ' '&& tempchars[p] != ','&&tempchars[p]!='\0') { p++; }//将这个单词的开始位置和结束位置作标记
                    tempword = tep.substring(a, p);//将这个单词截取下来
                    for(int i=0;i<stopword.size();i++)//将单词与停用词表进行对比
 { if(tempword.equals(stopword.get(i))) { s++; } } p=p-1;//当前p指向单词间的分隔符,退回到此字符的前两个
 } } flag = 1; p++; } } }
View Code

此段代码的主要逻辑是一个while循环,循环分析每个字符,以及当前对应的的状态。

读到每个字符则字符数加一。

读到每个换行符则行数加一,最后的行数还要加上第一行。

读到每个可显示字符,则判断前一个字符是否是单词分隔符,若是是则单词数加一;若是不是则前一个也是可显示字符,则为同一个单词,单词数不变。若是有停用词表,则将单词截取下来和词表中的单词进行对比。

public void analyseAddtion() { int i=0; int flag = 1; //此行是否分配
    int cflag = 0; //此行是否处于注释里
    int dflag = 0; // 此行是不是‘*/’的注释行
    int count =0; //每行有效字符计数
    while(tempchars[i] != '\0') { if(tempchars[i] == ' '||tempchars[i] == '\t'||tempchars[i] == '\r')//若是是空格一类的直接跳过
 { i++; } else if(tempchars[i] == '/') { count++; if(tempchars[i+1] == '/') { if(flag == 1 && count<3 && cflag == 0)//此种状况可直接判断为注释行
 { comment++; flag = 0; } } else if(tempchars[i+1] == '*') { cflag = 1; i++;//跳过一个字符,防止下一个是‘/’的状况
 } i++; } else if(tempchars[i] == '*') { count++; if(tempchars[i+1] == '/') { if(cflag ==1) { cflag = 0; i++;//跳过一个字符,防止下一个是‘*’的状况
                    count = 0; dflag = 1; } } i++; } else if(tempchars[i] == '\n')//到每行末尾,若此行没有分配则根据当前状态进行分配
 { if(flag == 1 && cflag == 0 && dflag == 0 && count<2) { empty++; flag = 0; } if(flag == 1 && cflag == 0 && dflag == 0 && count>1) { code++; flag = 0; } if(flag == 1 && cflag == 1) { comment++; flag = 0; } if(flag == 1 && cflag == 0 && dflag == 1) { comment++; flag = 0; dflag = 0; } count = 0; flag = 1; i++; } else//若是是其余字符
 { count++; if(count > 1 && flag == 1 && cflag == 0)//此种状况可直接判断为代码行
 { code++; flag = 0; } i++; } } //若最后一行没有分配,会经过当前状态进行分配
    if(flag == 1 && dflag == 1) { comment++; } if(flag == 1 && cflag == 1) { comment++; } if(flag == 1 && cflag == 0 && dflag == 0 && count<2) { empty++; } if(flag == 1 && cflag == 0 && dflag == 0 && count>1) { code++; } }
View Code

此段代码的主要逻辑也是while循环,循环分析每个字符,以及当前对应的的状态。

若是读到空格,制表符和回车符,则直接跳过,这个对判断行没有影响。

若是读到’/’,则判断下一个是否是’/’,若是是且此行没有肯定是什么行,并且此行当前的可显示字符数不超过两个而且不在注释范围内 ,则可判断是注释行。若是下一个是’*’,则此行进入注释范围内(须要’*/’才能消除此注释范围)。

若是读到’*’,则判断下一个是否是’/’,若是是,判断是否在注释范围。若是在,退出注释范围,将当前可显示字符数清零,不在则当作两个可显示字符便可。

若是读到‘\n’,到了每行末尾,如此行还没肯定是什么行,则根据当前的状态判断,便是否在注释范围,是不是’*/’的注释行,是不是空行等。

最后在退出时,也会判断最后一的状态,肯定是什么行。

for(int i=0; i<args.length;i++)//循环判断每个字符串
 { if(args[i].equals("-c")) { func[0] = true; if((i+1) == args.length)//若是此字符串为最后一个,则不符合格式,下同
 { error = true; break; } if(args[i+1].charAt(0) != '-')//若是下一个不是'-'开头的指令,则默认为文件名,进行读取,下同
 { i++; filename = args[i]; } } else if(args[i].equals("-w")) { func[1] = true; if((i+1) == args.length) { error = true; break; } if(args[i+1].charAt(0) != '-') { i++; filename = args[i]; } } else if(args[i].equals("-l")) { func[2] = true; if((i+1) == args.length) { error = true; break; } if(args[i+1].charAt(0) != '-') { i++; filename = args[i]; } } else if(args[i].equals("-o")) { func[3] = true; if((i+1) == args.length) { error = true; break; } i++; outputfile = args[i];//'-o'指令后必须接输出文件名,进行读取
 } else if(args[i].equals("-e")) { func[4] = true; if((i+1) == args.length) { error = true; break; } i++; stoplistfile = args[i];//'-e'指令后必须接停用词表文件名,进行读取
 } else if(args[i].equals("-a")) { func[5] = true; if((i+1) == args.length) { error = true; break; } if(args[i+1].charAt(0) != '-') { i++; filename = args[i]; } } else if(args[i].equals("-s")) { func[6] = true; if((i+1) == args.length) { error = true; break; } if(args[i+1].charAt(0) != '-') { i++; filename = args[i]; } } else { error = true; break; } }
View Code

循环判断,主函数自带的参数,是一个字符串数组。由此分析指令。’-c’, ’-w’, ’-l’, ’-a’指令后面若接文件名则是待分析的文件名,进行读取。‘-o’后接的文件名必然是输出文件名,’-e’后接的文件名必然是停用词表。分析后则可获得程序须要完成哪些功能,并接受到指令中相应的文件名。

 

5、测试设计过程

经过11个测试用例和13个执行语句来对程序进行测试。每一个测试用例均对于不一样的功能有所侧重,覆盖了系统能实现的绝大部分功能。根据白盒测试的思想,测试用例能也能覆盖绝大部分的条件判断语句。用例中出现换行和文件结尾时容易致使程序高风险,用例的字符数太高引发数组越界也会形成高风险。此测试方案基本能知足对此程序功能测试要求。如下会对每一个测试用例进行阐释和具体说明。

测试1:

用例:file1.c

用例说明:用于测试字符统计的基本功能,此用例包含了空格和制表符,测试可否正确统计空格即制表符。

执行语句:-c file1.c -o output1.txt

预计输出:file1.c,字符数:15

 

测试2:

用例:file2.c

用例说明::用于测试字符统计的基本功能,此用例包含空行,测试可否统计换行字符。

执行语句:-c file2.c -o output2.txt

预计输出:file2.c,字符数:22

 

测试3:

用例:file3.c

用例说明:用于测试单词统计的基本功能,此用例包含换行,空格,逗号隔开,测试可否正确统计单词数。

执行语句:-w file3.c -o output3.txt

预计输出:file3.c,单词数:16

 

测试4:

用例:file4.c

用例说明:用于测试停用词表功能,此用例测试基本功能,测试可否将例子中须要屏蔽的单词屏蔽。

执行语句:-w file4.c -e stoplist.txt -o output4.txt

预计输出:

file4.c,单词数:13

file4.c,停用后单词数:10

 

测试5:

用例:file5.c

用例说明:用于测试停用词表功能,此用例包含单词中含有停用词表的单词但不等于此单词,测试是否会误判断屏蔽。

执行语句:-w file5.c -e stoplist2.txt -o output5.txt

预计输出:

file5.c,单词数:20

file5.c,停用后单词数:20

 

测试6:

用例:file6.c

用例说明:用于测试行统计功能,此用例测试基础功能,包含空行,只有一个字符的行等。

执行语句:-l file6.c -o output6.txt

预计输出:file6.c,行数:9

 

测试7:

用例:file7.c

用例说明:用于测试代码行和注释行,此用例包含容易混淆的代码行和注释行的状况,测试可否正确统计行数。

执行语句:-a file7.c -o output7.txt

预计输出:file7.c,代码行/空行/注释行: 6/0/3

 

测试8:

用例:file8.c

用例说明:用于测试代码行和空行,此用例包含不少容易混淆的空行和注释行的状况,测试是否能正确统计行数。

执行语句:-a file8.c -o output8.txt

预计输出:file8.c,代码行/空行/注释行: 0/1/4

测试9:

用例:file9.c

用例说明:用于测试空行和代码行,此用例包含容易混淆的代码行和空行的状况,测试时候能正确统计行数。

执行语句:-a file9.c -o output9.txt

预计输出:file9.c,代码行/空行/注释行: 2/4/0

 

测试10:

用例:file10.c

用例说明:用于测试代码行,空行,注释行。此用例为综合用例,包含各类可能混淆的状况,测试可否正确统计行数。

执行语句:-a file10.c -o output10.txt

预计输出:file10.c,代码行/空行/注释行: 11/1/16

 

测试11:

用例:file1.c

用例说明:用来测试在不提供制定输出文件下,可否将结果输出在默认文件result.txt中。

执行语句:-l file1.c

预计输出:file1.c,字符数:15

 

测试12:

用例:当前文件夹中全部“.c”文件

用例说明:用于测试可否递归处理当前文件夹中全部符合条件的文件。

执行语句:-w -s .*.c -o output12.txt

预计输出:(较多不予以显示)

 

测试13:

用例:file11.c

用例说明:用于测试全功能,包含全部的功能指令,给出的用例中也包含了各类可能处理的状况,测试可否正常运行并给出正确的结果。

执行语句:-c -w -l -a -s *.c -e stoplist.txt -o output13.txt

预计输出:(较多不予以显示)

 

6、参考文献

【1】面向对象程序设计教程,任宏萍编著。

【2】https://www.cnblogs.com/yxwkf/p/4609765.html

【3】https://jingyan.baidu.com/article/0202781145eaab1bcc9ce5f0.html

相关文章
相关标签/搜索