2018软工实践第二次作业
软工实践第二次作业
一、GitHub地址
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 1250 | 2020 |
· Estimate | · 估计这个任务需要多少时间 | 1250 | 2020 |
Development | 开发 | 1200 | 1880 |
· Analysis | · 需求分析 (包括学习新技术) | 360 | 600 |
· Design Spec | · 生成设计文档 | 10 | 30 |
· Design Review | · 设计复审 | 10 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 30 |
· Design | · 具体设计 | 180 | 120 |
· Coding | · 具体编码 | 480 | 720 |
· Code Review | · 代码复审 | 30 | 120 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 240 |
Reporting | 报告 | 50 | 140 |
· Test Repor | · 测试报告 | 30 | 90 |
· Size Measurement | · 计算工作量 | 10 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 10 | 30 |
| | 合计 |1250 |2020
三、解题思路描述
按照题目的要求,统计input.txt中的以下几个指标
- 统计文件的字符数:
只需要统计Ascii码,汉字不需考虑
空格,水平制表符,换行符,均算字符 - 统计文件的单词总数,单词:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。
英文字母: A-Z,a-z
字母数字符号:A-Z, a-z,0-9
分割符:空格,非字母数字符号
例:file123是一个单词, 123file不是一个单词。file,File和FILE是同一个单词 - 统计文件的有效行数:任何包含非空白字符的行,都需要统计。
- 统计文件中各单词的出现次数,最终只输出频率最高的10个。频率相同的单词,优先输出字典序靠前的单词。
- 按照字典序输出到文件result.txt:例如,windows95,windows98和windows2000同时出现时,则先输出windows2000
- 输出的单词统一为小写格式
1.统计行数
由于只需要统计包含非空白字符的行,所以空白行可以忽略不计。我采用的方法的是逐行读取,读到非空白字符则行数加一;
2.统计字符数
由于题目要求只需要统计Ascii码,汉字不需考虑,所以我去学习了正则表达式,使用正则表达式判断字符是否满足要求,满足则字符数加一;
3.统计单词数,输出频率最高的十个
题目对有效单词的要求是至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。一开始我是先分割字符串,然后使用正则表达式判断,但是之后注意到题目中对分隔符的定义是空格和非字母数字符号。所以像汉字这样的字符也需要当作分隔符,我在分割字符串前先对整个字符串进行遍历,将非字母数字符号替换成空格,再进行分割,然后通过正则判断并统计单词个数。将得到的单词进行小写转换后存入一个HashMap<String, Integer>类型的变量map,并在存入时更新该单词的频率;
4.将结果输出到result.txt
使用System.setOut()输出到目标文件;
5.查找的资料
这次使用的是之前没学过的JAVA,所以很多东西都需要现学现用,主要是翻阅《Java 从入门到精通》来进行学习,在网上也查找了正则表达式的使用,BufferedReader和HashMap<String, Integer>等等的资料。
四、设计实现过程
结构设计图
单元测试
1.空白文本
2.错误文件名
3.多个输入参数
4.包含相同单词(如abcd和ABCD)
5.超过十个合法单词
6.包含非空白字符但无有效单词
7.全部为空白字符
8.包含汉字的文本
9.全部为有效单词的文本
10.单词长度全部小于4的文本
单元测试结果如下
单元测试覆盖率如图所示
五、性能分析
测试的时候循环运行了100000次,一共用了86.014s,
可以看出最耗时间的是java.io.PrintStream以及java.io.FileOutputStream,
分别占用了35.8%和16.6%的时间,在IO方面花费的时间是最多的;下面是对内存使用的分析
六、部分代码说明
CharacterCount.java 统计字符数
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CharacterCount {
public int charCount(String string) throws IOException {
int characters = 0;
String regex = "\\p{ASCII}"; //正则表达式判断字符是否合法
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
characters++; //统计字符数
}
return characters - 1;
}
}
most.java 输出十个词频最高的单词
import java.util.*;
public class most {
public List<Map.Entry<String, Integer>> mostWord(HashMap<String, Integer> map) {
// 将HashMap类型转换为list类型
List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
//对单词进行排序
list.sort(new MapComparator());
if (list.size() < 10) {
return list.subList(0, list.size());
}
else {
return list.subList(0, 10);
}
}
private class MapComparator implements Comparator<Map.Entry<String, Integer>> {
public int compare(Map.Entry<String, Integer> word1, Map.Entry<String, Integer> word2) {
//词频不等则按词频排序
//相等则按字典序排序
if (word1.getValue().compareTo(word2.getValue()) != 0) {
return word2.getValue().compareTo(word1.getValue());
}
else {
return word1.getKey().compareTo(word2.getKey());
}
}
}
}
由于刚开始学习Java,对Java的使用还不太熟悉,有部分代码借鉴于:https://github.com/Dark-Existed
异常处理
无输入参数时,输出"Error: No input file name!";
输入参数有多个时,输出"Error: Please enter one file name!";
String path = "";
if (args == null) {
System.out.println("Error: No input file name!");
}
else if (args.length > 1) {
System.out.println("Error: Please enter one file name!");
}
else {
path = args[0];
}
七、总结和感想
- 这次的作业用的是Java来写的,做之前有在C++ 还有Java之间纠结过到底用哪种语言,Java对于我有点陌生,但是考虑到C++ 虽然学过,但自己使用的不多,还不如给自己点压力用Java来完成。过程还是挺的不容易,一开始两眼一抹黑都不知道从何做起,自己一边学一边实现,不会的上网百度查找资料,多亏了舍友志炜大佬在旁指导我,给予我一些提示和帮助最终才完成了这个任务。虽然完成的挺不容易,但是之中还是学到了不少,懂得了Java的一点使用方法,懂得了代码封装,也懂得了《构建之法》中所说的一个项目的完成并不是简简单单地敲完代码就完成了,还包括了需求分析,单元测试,异常处理等等。这次的个人项目对于我来说是一个很大的挑战,虽然作业完成的或许还不够好,存在着或多或少的缺陷,但是我觉得我这次的收获已经蛮多了,自己的学习之路还有很长,接下来的日子继续努力吧!