第二周作业 WordCount
一、Github 地址
https://github.com/llag9810/Software-Quality-and-Testing-Wordcount
二、PSP2.1 表格
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
60 |
25 |
· Estimate |
· 估计这个任务需要多少时间 |
30 |
15 |
Development |
开发 |
600 |
810 |
· Analysis |
· 需求分析 (包括学习新技术) |
60 |
60 |
· Design Spec |
· 生成设计文档 |
30 |
30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
0 |
0 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 |
20 |
· Design |
· 具体设计 |
20 |
40 |
· Coding |
· 具体编码 |
250 |
350 |
· Code Review |
· 代码复审 |
40 |
40 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
60 |
100 |
Reporting |
报告 |
60 |
85 |
· Test Report |
· 测试报告 |
40 |
60 |
· Size Measurement |
· 计算工作量 |
10 |
5 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
10 |
20 |
|
合计 |
660 |
835 |
三、解题思路
1. 解析参数。Java 语言的参数在 main 方法里为一个 args 数组,根据这个数组来解析参数。其中包括两个方面,一是判断参数输入的合法性,二是解析参数的作用(即需要哪些功能)。
2. 针对文件读写设计函数。使用 JAVA 中的输入、输出流进行封装,完成文件的读取和结果的写入操作。
3. 实现单词、字符、行数的读写。其中,行数的读取比较简单,每读一行就加1。字符的读取同理。单词的读取可以使用 java 中的 Scanner,用正则表达式将分界符(delimiter)设置成空格、逗号、tab和换行,这样每次读一个word即可。
4. 实现stoplist:将stoplist文件里面的内容读到一个 HashSet 中,每次判断读到的单词在不在 HashSet 中,如果在则单词不算。
5. 实现注释、代码行、空行判断:使用正则表达式按行判断即可。
四、代码说明
我的代码包含两个文件,Main.java 包含主函数和参数解析、文件打开关闭部分,Counter.java 实现了计数功能。
我这里贴出核心部分,即计数部分的源代码。代码内容参见注释:
1 /** 2 * Count the number of chars in the input stream. 3 * @param is the InputStream to count. 4 * @param ps the PrintStream to write the result. 5 */ 6 public void countChar(InputStream is, PrintStream ps) { 7 try { 8 int count = is.available(); 9 String note = ", " + "字符数: "; 10 ps.println(fileName + note + count); 11 } catch (IOException e) { 12 e.printStackTrace(); 13 } 14 } 15 16 17 /** 18 * Count the number of lines in the input stream. 19 * @param is the InputStream to count. 20 * @param ps the PrintStream to write the result. 21 */ 22 public void countLines(InputStream is, PrintStream ps) { 23 Scanner scanner = new Scanner(is); 24 int line = 0; 25 while (scanner.hasNextLine()) { 26 line++; 27 scanner.nextLine(); 28 } 29 String note = ", " + "行数: "; 30 ps.println(fileName + note + line); 31 } 32 33 34 /** 35 * Count words without StopList. 36 * 37 * @see #countWordsWithStopList(InputStream, PrintStream, Set) 38 */ 39 public void countWords(InputStream is, PrintStream ps) { 40 countWordsWithStopList(is, ps, null); 41 } 42 43 /** 44 * Count the number of words in the input stream. 45 * According to the requirements, the only 4 legal delimiters are: 46 * space, comma, tab and line break; 47 * 48 * @param is the InputStream to count. 49 * @param ps the PrintStream to write the result. 50 * @param stopSet A set of words that shall not be included into the count. 51 */ 52 public void countWordsWithStopList(InputStream is, PrintStream ps, Set<String> stopSet) { 53 Scanner scanner = new Scanner(is); 54 int words = 0; 55 56 Pattern pattern = Pattern.compile("\\n+|\\t+|\\s+|,"); 57 scanner.useDelimiter(pattern); 58 while (scanner.hasNext()) { 59 String word = scanner.next(); 60 if (stopSet == null || !stopSet.contains(word)) { 61 words++; 62 } 63 } 64 65 String note = ", " + "单词数: "; 66 ps.println(fileName + note + words); 67 } 68 69 /** 70 * Count the lines of code, comment and blank. 71 */ 72 public void countCodeAndComment(InputStream is, PrintStream ps) { 73 Scanner scanner = new Scanner(is); 74 int code = 0; 75 int blank = 0; 76 int comment = 0; 77 String blankPattern = "[\\s\\t\\n]*[(){}]?"; 78 String commentPattern = "([\\s\\t]*([})]?)((/\\*|//).*))|(\\*/)"; 79 while (scanner.hasNextLine()) { 80 String line = scanner.nextLine(); 81 if (Pattern.matches(blankPattern, line)) { 82 blank++; 83 } else if (Pattern.matches(commentPattern, line)) { 84 comment++; 85 } else { 86 code++; 87 } 88 } 89 String note = ", " + "代码行/空行/注释行: "; 90 ps.println(fileName + note + code + "/" + blank + "/" + comment); 91 }
五、测试
我设置了如下几个测试用例来测试不同的功能是否完全实现
1 wc.exe -a file.c 2 wc.exe -w file.c 3 wc.exe -c file.c 4 wc.exe -l file.c
5 wc.exe -w -c -l -a -s D:\test\*.c
6 wc.exe -e stop.txt -o testo.txt -a file.c
7 wc.exe -l -w -a -c -s ../test/ -e ../stop.txt -o output.txt