WordCount 实现与测试
WordCount 实现与测试
一、github地址
https://github.com/TCZdudu/WCProject
二、PSP表格
PSP2.1 | PSP阶段 | 预估耗时(分钟) | 实际耗时 |
---|---|---|---|
Planning | 计划 | 20 | 15 |
· Estimate | · 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 700 | 840 |
· Analysis | · 需求分析 (包括学习新技术) | 100 | 120 |
· Design Spec | · 生成设计文档 | 20 | 20 |
· Design Review | · 设计复审 (和同事审核设计文档) | 10 | 10 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 20 | 30 |
· Design | · 具体设计 | 100 | 150 |
· Coding | · 具体编码 | 200 | 240 |
· Code Review | · 代码复审 | 100 | 120 |
· Test | · 测试(自我测试,修改代码,提交修改) | 150 | 150 |
Reporting | 报告 | 180 | 200 |
· Test Report | · 测试报告 | 100 | 120 |
· Size Measurement | · 计算工作量 | 20 | 20 |
· Postmortem & ProcessImprovement Plan | · 事后总结, 并提出过程改进计划 | 60 | 60 |
合计 | 920 | 1075 |
三、 解题思路
-
看到这个题目后,首先想到的是要读文件和写文件操作。java有很多读取文件的方法,最终还是选择了BufferedReader。read()函数一次读取一个字符,而readline()一次读取一行。
-
对字符,单词,行等等的判断,我马上想到了编译器里的词法分析,并不完全一样,但是大概得思路有一些。
-
很复杂的是,对输入的不同命令要判断,并根据不同的命令执行不同的功能,并在输入的命令中找出不同文件名的作用。
-
最后是java转成exe,至今没想通,要用exe测试为什么要用java写。
四、 程序设计实现过程
-
代码主要函数有9个,主要就是每个不同命令的不同功能。
-
实现统计字符、单词、行数着手,这就是对从文件读取的字符串的处理,很常规,也不是很麻烦。
-
再进行对代码行分辨,递归处理文件和停用词功能。代码行的种类有两种
//
和/**/
,//
好判断,本行有就是代码行,/**/
之间的代码也算代码行,所以有头就要有尾,记住头的位置,再找到末端位置就可以判断总的行数。空行也很简单,记录不在/**/
内的空行或{
}
,用之前记录的总行数减掉这空行和注释行就得到代码行。停用词是统计停用词个数,减掉。 -
实现了功能之后在处理输入命令后的分析,用条件语句去分析实现不同命令对应的不同功能实现。
五、 代码说明
介绍一下几个主要函数的实现
下面是获取停用词的函数,当输入
-e
时调用,先获取stoplist.txt中的词保存在一个list中,然后统计出现里面词的次数
public static List<String> get_stop(String args[])throws IOException{
//包含“-e”时,获取stoplist中的单词作为停用词
List<String> input_args = Arrays.asList(args);
List<String> stop_words = new ArrayList<String>();
if (input_args.contains("-e")) {
int index = input_args.indexOf("-e");
String stopFile = input_args.get(index + 1);
BufferedReader buffer = null;
buffer = new BufferedReader(new FileReader(stopFile));
stop_words = getStopList(buffer);
}
return stop_words;
}
public static int get_stop_num(String filename,List<String> stop_list)throws IOException{
//获取停用词数目
FileReader f_obj = new FileReader(filename);
BufferedReader b_obj = new BufferedReader(f_obj);
String str;
int num_stop=0;
while ((str = b_obj.readLine()) != null) {
for (String s : str.split(" ")) {
for (String s1 : s.split(",")) {
if (s1.length() > 0 && stop_list.contains(s1)) {
num_stop++;
}
}
}
}
return num_stop;
}
判断代码行、空行、注释行数目。先统计非注释的空行,再统计
//
和/**/
类的代码行,最后总数目减去空行和注释行得到代码行
public static String get_line_info(String filename)throws IOException{
//统计代码行、空行、注释行数目
int blank_line_num =0,code_line_num = 0,note_line_num = 0;
FileReader f_obj = new FileReader(filename);
String result;
BufferedReader b_obj = new BufferedReader(f_obj);
int line_num = 0;
String str_line = null;
while ((str_line = b_obj.readLine()) != null) {
if (str_line.length() == 0 || str_line.equals("{" )|| str_line.equals("}")) {
blank_line_num++; //统计空行
} else {
for (int i = 0; i < str_line.length()-1; i++) {
boolean flag2=true;
while (str_line.charAt(i) != ' ' && str_line.charAt(i) != '\t' && flag2) {
if (str_line.charAt(i) == '/' && str_line.charAt(i + 1) == '/') {
note_line_num++; //统计//形式的注释行
i = str_line.length();
break;
} else if (str_line.charAt(i) == '/' && str_line.charAt(i + 1) == '*') {
boolean flag=true;//统计形如/**/的注释行数目
for (int t = str_line.length()-1; t >= 0; t--) {
while (str_line.charAt(t) != ' ' && str_line.charAt(t) != '\t'&& t>=1) {
if (str_line.charAt(t) == '/' && str_line.charAt(t - 1) == '*') {
t = -1; //本行末尾结束 直接加1 并不进行后续代码
flag =false;
flag2=false;
break;
}
else break;
}
}
note_line_num +=1;
while (flag) { //非本行结束 往下判断 找到代码行结束位置
if((str_line = b_obj.readLine()) != null) {
note_line_num++;
line_num++;
for (int j = str_line.length() - 1; j >= 0; j--) {
while (str_line.charAt(j) != ' ' && str_line.charAt(j) != '\t' && j >= 1) {
if(str_line.charAt(0) == '*' && str_line.charAt(j - 1) == '/' && str_line.length() > 2) {
note_line_num -= 1;
j = -1;
flag = false;
break;
}
else if (str_line.charAt(j) == '/' && str_line.charAt(j - 1) == '*') {
j = -1;
flag = false;
break;
}
else break;
}
}
}
}
}
else {
break;
}
}
}
}
line_num++; //统计总代码行数
}
code_line_num = line_num - note_line_num -blank_line_num; //代码行 = 总行数 - 空行 -注释行
result = filename +",代码行/空行/注释行:"+ code_line_num +"/" + blank_line_num + "/" +note_line_num + "\r\n";
return result;
}
对输入的命令进行判断,实现不同的功能
public static void out_result(String filename,BufferedWriter file_writer,String args[],int args_len )throws IOException{
String character_num= "",line_num="",line_info="", word_num = ""; //判定执行哪些命令
int word_numb = -1;
String arg;
for (int i=0; i<args_len; i++){
arg = args[i];
switch (arg){
case "-c":
character_num = get_character_count(filename);
break;
case "-w":
word_numb = get_word_count(filename);
break;
case "-l":
line_num = get_line_count(filename);
break;
case "-a":
line_info = get_line_info(filename);
break;
case "-e":
List<String> stop_list = get_stop(args);
int num_stop = get_stop_num(filename,stop_list);
word_numb -= num_stop;
}
}
if(word_numb >=0){
word_num = filename + ",单词数:"+ word_numb +"\r\n";
}
get_result(file_writer,character_num);
get_result(file_writer,word_num);
get_result(file_writer,line_num);
get_result(file_writer,line_info);
}
六、 测试设计过程
获取停用词数目代码测试:
String str;
int num_stop=0;
while ((str = b_obj.readLine()) != null) {
for (String s : str.split(" ")) {
for (String s1 : s.split(",")) {
if (s1.length() > 0 && stop_list.contains(s1)) {
num_stop++;
}
}
}
}
return num_stop;
流程图如下
测试如下:
测试 | 输入 | 预期输出 | 实际输出 |
---|---|---|---|
ABF | EOF | ||
ABCF | 1 | 0 | 0 |
ABCDF | 1 | 0 | 0 |
ABCDEF | 1 | 1 | 1 |
获取结果代码测试:
String character_num= "",line_num="",line_info="", word_num = ""; //判定执行哪些命令
int word_numb = -1;
String arg;
for (int i=0; i<args_len; i++){
arg = args[i];
switch (arg){
case "-c":
character_num = get_character_count(filename);
break;
case "-w":
word_numb = get_word_count(filename);
break;
case "-l":
line_num = get_line_count(filename);
break;
case "-a":
line_info = get_line_info(filename);
break;
case "-e":
List<String> stop_list = get_stop(args);
int num_stop = get_stop_num(filename,stop_list);
word_numb -= num_stop;
}
}
流程图如下
测试如下:
测试 | 输入 | 预期输出 | 实际输出 |
---|---|---|---|
ABF | 0 | ||
ABCG | 1 | 1 | 1 |
ABDG | 1 | 1 | 1 |
ABEG | 1 | 1 | 1 |
ABFG | 1 | 1 | 1 |
获取单词数的代码测试:
int flag;
int word_num = 0;
boolean first_count = true;
while((flag = b_obj.read()) != -1){
if (first_count){
if(flag != ',' && flag != ' ' && flag != '\n' && flag !='\r' && flag != '\t')
word_num += 1;
first_count = false;
}
if (flag == ',' || flag == ' ' || flag == '\n'||flag =='\r' || flag == '\t' ){
first_count = false;
while((flag = b_obj.read()) != -1 ){
if (flag != ',' && flag != ' '&& flag != '\n' && flag !='\r' && flag != '\t'){
word_num ++;
break;
}
}
}
}
return word_num;
流程图如下
测试如下:
测试 | 输入 | 预期输出 | 实际输出 |
---|---|---|---|
ABH | 0 | ||
ABCDH | 1 | 1 | 1 |
ABCFH | 1 | 0 | 0 |
ABCFEGH | 1 | 0 | 0 |
ABCDCFEGH | 1 | 1 | 1 |