第二周作业WordCount
第二周作业心得
github项目地址
https://github.com/ChAnYaNG97/WordCount
PSP表格
PSP2.1 | PSP阶段 | 预估耗时 (分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 10 |
· Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 575 | 1180 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 60 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 5 | 10 |
· Design | · 具体设计 | 30 | 60 |
· Coding | · 具体编码 | 300 | 500 |
· Code Review | · 代码复审 | 30 | 200 |
· Test | · 测试(自我测试,修改代码,提交修改) | 100 | 320 |
Reporting | 报告 | 45 | 55 |
· Test Report | · 测试报告 | 30 | 40 |
· Size Measurement | · 计算工作量 | 5 | 5 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 10 |
合计 | 630 | 1345 |
解题思路
刚拿到题目的时候,觉得这个程序功能并不复杂,而且与编译原理课程中编写的词法分析器有很多相似之处。但是我想到当时手写词法分析器的时候,十分繁琐,特别是一些边界条件的处理总是判断不好。后来想到flex/bison中使用正则表达式来进行词法分析,觉得这是一个非常容易实现的思路,所以就决定使用正则表达式来编写WordCount。
1.在网络上查找了正则表达式手册[1],知道了常用的正则表达式的写法
2.查找Java源程序如何打包为jar包,并转成exe格式的方法[2]
程序设计实现过程
因为代码是围绕文本处理来进行,所以只设计了一个类WordCount,一共有如下个函数:
public int countWord();
public int countLine();
public int countChar();
public int countEmptyLine();
public int countCommentLine();
public int countCodeLine();
public int countWordWithStopList();
这些函数之间的关系并不是很大,在countCodeLine()
中调用了countCommentLine(),countEmptyLine(), countLine()
。
后面会看到这些函数的具体实现都很简单,所以不太需要流程图来辅助说明。
代码说明
将要统计的文件读入一个String类型的buffer变量中
则行数可以按照下列方式统计:
public int countLine()
{
if(buffer.length() == 0)
return 0;
String[] lines = buffer.split("\n", -1);
return lines.length;
}
同理,字符数是按照,\space\t\n
来进行分割的,则字符数统计方式为
public int countWord()
{
if(buffer.length() == 0)
return 0;
String[] words = buffer.split("[, \t\n]+");
return words.length;
}
对于空行,写出空行对应的正则表达式[\\s]*[\\S]?[\\s]*
然后用这个正则表达式去匹配文本内容即可:
public int countEmptyLine()
{
if(buffer.length() == 0) return 0;
String regex = "[\\s]*[\\S]?[\\s]*";
Pattern emptyLinePattern = Pattern.compile(regex);
String[] lines = buffer.split("\n", -1);
Matcher matcher;
int result = 0;
for(String line : lines)
{
matcher = emptyLinePattern.matcher(line);
if(matcher.matches())
result++;
}
return result;
}
同理,注释行的正则表达式为(//.*\\n)|(/\\*(.|\\n)*\\*/[\\n]?)
,函数编写方法与空行类似。
public int countCommentLine()
{
if(buffer.length() == 0) return 0;
String temp = "";
String regex = "(//.*\\n)|(/\\*(.|\\n)*\\*/[\\n]?)";
Pattern commentPattern = Pattern.compile(regex);
Matcher matcher = commentPattern.matcher(buffer);
while(matcher.find())
{
temp += matcher.group();
}
if(temp.equals("")) return 0;
return temp.split("\n").length;
}
代码行数的计算方式用代码行数 = 总行数 - 空行数 - 注释行数
即可。
测试设计过程
1.统计单词数,行数,代码行数
-c 统计字符数
路径 | 输入 | 预期输出 | 实际输出 |
---|---|---|---|
A-B-C | null | 0 | 0 |
A-B-D | a\n | 2 | 2 |
-l 统计行数
路径 | 输入 | 预期输出 | 实际输出 |
---|---|---|---|
A-B-C | null | 0 | 0 |
A-B-D | abc\nabc | 2 | 2 |
-w 统计单词数
路径 | 输入 | 预期输出 | 实际输出 |
---|---|---|---|
A-B-C | null | 0 | 0 |
A-B-D | dog cat mouse | 3 | 3 |
2.统计空行数,注释行数
路径 | 输入 | 预期输出 | 实际输出 |
---|---|---|---|
A-B-D | null | 空行数:0,注释行数:0 | 空行数:0,注释行数:0 |
A-B-C-E-G | "}//" | 空行数:0,注释行数:1 | 空行数:0,注释行数:1 |
A-B-C-E-F | "\t\t\nabc\n\t\t" | 空行数:2,注释行数:0 | 空行数:2,注释行数:0 |
对于一些文件的测试用例:
file.c的内容如下:
File write,name = new File(outputPath);
writename.createNe|wFile();
Buffe,redWriter out = new BufferedWrit,er(new FileWriter(writename));
out.close();
stopList.txt内容如下:
out = file else void
输入 | 预期输出 | 实际输出 |
---|---|---|
wc.exe -w file.c | file.c,单词数:16 | file.c,单词数:16 |
wc.exe -l file.c | file.c,行数:4 | file.c,行数:4 |
wc.exe -c file.c | file.c,字符数:186 | file.c,字符数:186 |
wc.exe -w -l -c file.c | file.c,字符数:186 file.c,单词数:16 file.c,行数:4 |
file.c,字符数:186 file.c,单词数:16 file.c,行数:4 |
wc.exe -a file.c | file.c,代码行/空行/注释行:4/0/0 | file.c,代码行/空行/注释行:4/0/0 |
wc.exe -w -l -c empty.c | empty.c,字符数:0 empty.c,单词数:0 empty.c,行数:0 |
empty.c,字符数:0 empty.c,单词数:0 empty.c,行数:0 |
wc.exe -w -l -c -a file.c | file.c,字符数:186 file.c,单词数:16 file.c,行数:4 file.c,代码行/空行/注释行:4/0/0 |
file.c,字符数:186 file.c,单词数:16 file.c,行数:4 file.c,代码行/空行/注释行:4/0/0 |
wc.exe -s -w -l -c -a *.c | file2.c,字符数:1 file2.c,单词数:0 file2.c,行数:2 file2.c,代码行/空行/注释行:0/2/0 aaa.c,字符数:1 aaa.c,单词数:0 aaa.c,行数:2 aaa.c,代码行/空行/注释行:0/2/0 file.c,字符数:186 file.c,单词数:16 file.c,行数:4 file.c,代码行/空行/注释行:4/0/0 |
file2.c,字符数:1 file2.c,单词数:0 file2.c,行数:2 file2.c,代码行/空行/注释行:0/2/0 aaa.c,字符数:1 aaa.c,单词数:0 aaa.c,行数:2 aaa.c,代码行/空行/注释行:0/2/0 file.c,字符数:186 file.c,单词数:16 file.c,行数:4 file.c,代码行/空行/注释行:4/0/0 |
wc.exe -w -l -c -o output.txt | output.txt | output.txt |
wc.exe -w -l -c -a -e stopList.txt | file2.c,字符数:1 file2.c,单词数:0 file2.c,行数:2 file2.c,代码行/空行/注释行:0/2/0 aaa.c,字符数:1 aaa.c,单词数:0 aaa.c,行数:2 aaa.c,代码行/空行/注释行:0/2/0 file.c,字符数:186 file.c,单词数:14 file.c,行数:4 file.c,代码行/空行/注释行:4/0/0 |
file2.c,字符数:1 file2.c,单词数:0 file2.c,行数:2 file2.c,代码行/空行/注释行:0/2/0 aaa.c,字符数:1 aaa.c,单词数:0 aaa.c,行数:2 aaa.c,代码行/空行/注释行:0/2/0 file.c,字符数:186 file.c,单词数:14 file.c,行数:4 file.c,代码行/空行/注释行:4/0/0 |
wc.exe -w -l -c -a -s *.c -e stopList.txt -o output2.txt | output2.txt |
output.txt内容如下:
file2.c,字符数:1
file2.c,行数:2
file2.c,单词数:0
file2.c,代码行/空行/注释行:0/2/0
aaa.c,字符数:0
aaa.c,行数:0
aaa.c,单词数:0
aaa.c,代码行/空行/注释行:0/0/0
file.c,字符数:186
file.c,行数:4
file.c,单词数:14
file.c,代码行/空行/注释行:4/0/0
读写文件部分其实是高风险代码,但是也都有try,catch和exception的处理。
测试脚本
test.bat
#(test1.c是空文件)
wc.exe -w -l -c test\test1.c
#(test2.c是单字符文件)
wc.exe -w -l -c test\test2.c
#(test3.c是全为符号的字符文件)
wc.exe -w -l -c -a test\test3.c
#(test4.c是普通的代码文件)
wc.exe -w -l -c test\test4.c -e stopList.txt
wc.exe -w -l -c -a test\test4.c -o output1.txt
wc.exe -w -l -c -a test\test4.c -e stopList.txt -o output2.txt
wc.exe -w -l -c -a -s test\*.c -e stopList.txt -o output3.txt
参考文献链接
[1] http://tool.oschina.net/uploads/apidocs/jquery/regexp.html
[2] http://blog.csdn.net/sunkun2013/article/details/13167099