第2周个人作业:WordCount编码和测试
github地址:https://github.com/ryan-sgy/WordCount
一.PSP表格
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
10 | 30 |
· Estimate |
· 估计这个任务需要多少时间 |
10 | 10 |
Development |
开发 |
4天 | 5天 |
· Analysis |
· 需求分析 (包括学习新技术) |
1天 | 1天 |
· Design Spec |
· 生成设计文档 |
- | - |
· Design Review |
· 设计复审 (和同事审核设计文档) |
- | - |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 | 30 |
· Design |
· 具体设计 |
120 | 200 |
· Coding |
· 具体编码 |
3天 | 3天 |
· Code Review |
· 代码复审 |
100 | 100 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
100 | 130 |
Reporting |
报告 |
30 | 30 |
· Test Report |
· 测试报告 |
30 | 30 |
· Size Measurement |
· 计算工作量 |
120 | 60 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
60 | 30 |
合计 |
11天 | 11天 |
二.解题思路
首先,使用的语言是Java,已经快一年没有使用了,先检查了一下jdk环境,简单的到网上了解了一下Java的各种使用方法,还好语言都是相通的,也逐渐回忆清楚Java的语言模式。
统计文件的字符数,单词数和行数,根据命令输出相应结果。具体操作如下:
- 接到用户输入,依次判断输入是否符合格式,并提取输入的关键内容,例如参数和路径,并根据参数设置相应的标志变量。
- 调用readFile函数,传进去所需要统计的文件路径,函数中根据标志变量的值进行相应的输出,同时将输出结果写入content,为了使有 -o参数时,可以传入相应的内容。
- 统计字符数,等于读入的字符串数+行数(使用readline会使每一行少一个字符)。
- 统计单词数,使用split("( |,)+")匹配逗号和空格的组合并将读入的文件字符串分开成字符串数组,数组的length即为单词数。
- 统计行数,每次readline即加一行。
- 输出文件,只需将输出结果时已经得到的content作为参数传入writeFile函数写到相应的文件即可,相应的文件路径从一开始的用户输入得到。
三.程序设计实现过程
因为功能比较简单,所以我就把所有的功能都写在一个类里面了,首先是基本功能,记录行数,词数和字符数,我写了lineCount(),wordCount()和charCount()三个函数来实现.至于-o输出到指定文件.,只需在main函数里做个判断就好了.然后就是扩展功能,首先是-s实现递归目录下符合条件的文件,我写了个searchFile()函数来实现,主要涉及到正则表达式和遍历时,对其是文件还是文件夹的判断的处理,然后是-a 返回更复杂的数据(代码行/空行/注释行)我用了一个otherCount()函数来实现,这个的难点在于读懂(代码行/空行/注释行)的定义,把各种情况考虑到了代码就很容易写了,-e就比较简单了包含这个参数,就去读它后面的文件,把停用词表包含在一个List。
四.代码说明
空行和不包含注释符号的代码行容易判断,包含注释符号的代码行稍稍复杂,通过split方法获得注释符号之前或之后的子串,再通过正则匹配判断其中是否含有代码,若有则该行仍为代码行,最后剩下的就是注释行。
public static int kindOfLine(String line){ //-1 empty 1 code 0 note String temp =""; if(line.trim().length() == 0) return -1; if(!line.contains("//") && !line.contains("/*") && !line.contains("*/")) //不含这些符号必是code return 1; if(line.contains("//")) // //之前的code temp = line.split("//")[0]; if(line.contains("/*")) // /*之前的code temp = line.split("/\\*")[0]; if(line.contains("*/")) // */之后的code temp = line.split("\\*/")[line.split("\\*/").length - 1]; if(temp.matches(".*\\w+.*")) // 含有字母或数字则该行是code return 1; return 0; }
构造函数接受File作为参数,通过BufferedReader每次读取一行,最终拼接成一个字符串,将其转换为字符数组,统计其长度可得字符数;按照题目对于单词的定义,将字符按照空格或逗号进行分割,统计分割后的非空字符串数即为单词数;调用kindOfLine获得行数信息。
构造函数重载接收file和stopList作为参数,统计单词数时剔除stopList中含有的单词。
public WordCount(File file) { BufferedReader bf; try { bf = new BufferedReader(new FileReader(file)); String temp1, temp2 = ""; while((temp1 = bf.readLine()) != null) { temp2 += temp1 + String.valueOf('\n'); line++; // 获取行数 int i = kindOfLine(temp1); // 获取行数详细信息 if(i == -1) emptyLine++; else if(i == 1) codeLine++; else noteLine++; for (String val: temp1.split(" |,")){ wordNum += val.equals("") ? 0 : 1; // 非空单词数 } } buffer = temp2.toCharArray(); bf.close(); charNum = buffer.length - 1; // 字符数 } catch (Exception e) { e.printStackTrace(); } } public WordCount(File file, HashSet<String> stopList)
// 根据输入进行判断并进行输出
for(File val : fileList) { String name = val.getName(); if(val.equals(stopFile) || val.equals(outputFile)){ continue; } if(isE){ wc = new WordCount(val, stopList); } else{ wc = new WordCount(val); } if(isC){ output = output + name + ",字符数: " + wc.getCharNum() + "\r\n"; } if(isW){ output = output + name + ",单词数: " + wc.getWordNum() + "\r\n"; } if(isL){ output = output + name + ",行数: " + wc.getLine() + "\r\n"; } if(isA){ output = output + name + ",代码行/空行/注释行: " + wc.getCodeLine() + "/" + wc.getEmptyLine() + "/" + wc.getNoteLine() + "\r\n"; } } BufferedWriter out = new BufferedWriter(new FileWriter(new File(curPath + "\\result.txt"))); out.write(output); out.flush(); out.close(); if(isO){ outputFile.createNewFile(); // 创建新文件 out = new BufferedWriter(new FileWriter(outputFile)); out.write(output); // \r\n即为换行 out.flush(); // 把缓存区内容压入文件 out.close(); // 关闭文件 }
五.测试过程设计
白盒的测试用例需要做到:
·保证一个模块中的所有独立路径至少 被使用一次
·对所有逻辑值均需测试 true 和 false
·在上下边界及可操作范围内运行所有循环
·检查内部数据结构以确保其有效性
设计以下10个测试用例(第一行为文件名,第二行为操作命令,之后为文件的内容): //test1.c //wc.exe -a test1.c int //test2.txt //wc.exe -a -l -w -c test2.txt -o output.c int //test3.c //wc.exe -a D:\test3.c int //test4.c //wc.exe -a test4.java int //test5.c //wc.exe -a test5.* int //test6.c //wc.exe -a test6.c int }// /* //test7.c //wc.exe -a -l -w -c test7.c -e stop.txt int,void //test8.c //wc.exe -a -l -w -c -s test8.c -e stop.txt int,void {// //test9.c //wc.exe -a -l -w -c -s *.c -e stop.txt int,void /* //test10.c //wc.exe -a -l -w -c -s *.c -e stop.txt -o D:\output.txt int,void */ main
结果:正确的测试用例都有正确的输出,错误的测试用例wc.exe会提示相应错误信息。
六.参考链接
- http://www.cnblogs.com/winterfells/p/7965596.html
- http://www.runoob.com/java/java-environment-setup.html
- http://blog.csdn.net/daxiang_zhang/article/details/2149896
- http://blog.csdn.net/hpchenqi_16/article/details/48504111
- http://blog.csdn.net/alex__0805/article/details/50895222.
- https://bbs.csdn.net/topics/390567815
- https://www.cnblogs.com/zhaoyan001/p/6077492.html
- http://www.cnblogs.com/winterfells/p/7965596.html
- http://www.runoob.com/java/java-environment-setup.html
- https://stackoverflow.com/questions/25555717/intellij-idea-javafx-artifact-build-does-not-generate-exe
- http://blog.csdn.net/daxiang_zhang/article/details/2149896
- http://blog.csdn.net/hpchenqi_16/article/details/48504111
- http://blog.csdn.net/alex__0805/article/details/50895222
- https://bbs.csdn.net/topics/390567815