软工网络 16个人作业2
软工网络 16个人作业2
1. 地址
2.个人的PSP表格。
PSP2.1 | 个人开发流程 | 预估耗费时间(分钟) | 实际耗费时间(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 55 |
Estimate | 明确需求和其他相关因素,估计每个阶段的时间成本 | 1000 | 1650 |
Development | 开发 | 180 | 200 |
Analysis | 需求分析 (包括学习新技术) | 180 | 190 |
Design Spec | 生成设计文档 | 40 | 40 |
Design Review | 设计复审 | 40 | 60 |
Coding Standard | 代码规范 | 15 | 15 |
Design | 具体设计 | 30 | 30 |
Coding | 具体编码 | 60 | 100 |
Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 40 | 60 |
Reporting | 报告 | 60 | 60 |
测试报告 | 30 | 30 | |
计算工作量 | 30 | 30 | |
事后总结,并提出过程改进计划 | 20 | 20 |
3、解题思路描述。
- 题目要求:
- 统计字符数
- 统计有效行数
- 统计单词数
- 统计词频并输出前十个单词
- 解题过程:
1、统计字符数
忽略汉字,空格、字母与数字的ASCII码值范围在32-126,换行符ASCII码值为10,水平制表符ASCII码值为9。
利用InputStreamReader输入流从文件中读取单个字符,定义一个字符计数器。循环读取单个字符,判断该字符的ASCII码值范围,满足条件,计数器加1。返回结果。
2、统计有效行数
利用输入流从文件中读取一行,判断是否为有效行数,有无字符串,满足条件则行数计数器加1。
3、统计单词数
利用输入流从文件中读取一行字符串,将其分割成单词,存入表中。返回表格的长度。
4、统计词频并输出前十个单词
建立集合map,逐个读取单词表中的单词,判断该词是否已存入集合,有则将该单词对应的value(即出现的次数)加1,没有就将该单词存入集合。将集合元素按照频数排序,最后进行输出结果。
4、设计实现过程
代码组织:将几个功能封装在几个函数中,再进行调用。
1、统计字符数
将要统计的文件的路径做为参数传入函数中,再按照解题思路中利用字符流逐个读取字符进行判断和统计。
设计函数num_of_char如下:
private static int num_of_char(String filename2) {
File file =new File(filename);
InputStreamReader r=null;//输入流读取单个字符
int c_num=0;//字符计数器
try {
r=new InputStreamReader(new FileInputStream(file));
int tempchar;//存放单个字符
try {
while((tempchar=r.read()) !=-1) {
if((tempchar >31&&tempchar<127)||tempchar==10||tempchar==9) { //读取的字符不包括汉字,但有包括换行符(10)和空格符
c_num++;
}
}
r.close();//关闭资源
} catch (IOException e) ;
}
} catch (FileNotFoundException e) {
System.out.println("文件不存在");
}
return c_num++;
}
2、统计有效行数
统计文件的路径作为传入参数,利用BufferedReader读取一行文件内容,判断是否为空,否则将计数器加一。
private static int num_of_line(String filename2) throws IOException {
File file =new File(filename);
int l_num=0;//行数计数器
BufferedReader r=null;
r=new BufferedReader(new FileReader(file));
String s=null;
while((s=r.readLine())!=null) {//读到一行,计数器加1
l_num=l_num+1;
}
r.close();
return l_num;
}
3、统计单词数
利用List存放文本的所有有效单词。统计文件的路径作为传入参数,利用BufferedReader读取一行文件内容,利用正则表达式"\\s*[^0-9a-zA-Z]+"
分割过滤除字母和数字以外的字符串。将所有字符串转为小写。进一步判断字符串是否含有数字(设计函数isNumberic(String str)),有数字,若满足以4个英文字母开头,跟上字母数字符号的格式(利用正则表达式),就将其加入单词表中;字符串中没有数字,例如:I,am,you等单词,也加入到单词表中。最后返回单词表的长度,即为单词总数。
//统计单词数
private static int num_of_word(String filename) throws IOException {
int w_num=0;
File file =new File(filename);
BufferedReader rf=null;
rf=new BufferedReader(new FileReader(file));
String s;
while((s=rf.readLine())!=null) {
String regex="\\s*[^0-9a-zA-Z]+";//正则表达式,过滤除字母和数字意外的特殊符号
String[] s2=s.split(regex);//分割字符串
for (String str : s2) {
String string=str.toLowerCase();//将单词转为小写
if(isNumberic(string)) {//判断字符串中有数字
if(string.length()>3) {//有数字,判断单词长度超过或等于4
if (string.matches("[a-zA-Z]{4,}[a-zA-Z0-9]*")) {//判断单词是否为4个字母加上数字,满足条件添加进表
lists.add(string);
}
}
}
else//字符串中没有数字
{
lists.add(string);
}
}
}
rf.close();
w_num=lists.size();
return w_num;
}
判断字符串中是否有数字函数
public static boolean isNumberic(String str) {
boolean re=false;
for(int i=0;i<str.length();i++){
if(Character.isDigit(str.charAt(i))){
re = true;
break;
}
}
return re;
}
4、统计词频并输出频数前10的单词
- 统计词频wro_fre()
将完成的单词表list逐一取出单词,存入集合wordMap中,其中集合的key值为单词,value值为单词出现的频数。当集合中不存在这个单词时,就将其add入集合中;若存在,就将该单词的频数即value加一。
//利用Map集合统计词频
public static void word_fre(){
int value;
for (String word : lists) {
if(wordMap.containsKey(word)) {
value=wordMap.get(word);
value++;
wordMap.put(word, value);
}
else {
wordMap.put(word, 1);
}
}
}
- 集合排序输出sortWord()
将单词集合利用覆盖Collection.sort()方法来进行集合键值对的排序。最后返回词频前10个单词的字符串数组。
//将map集合进行排序并返回前10个单词的字符串数组
public static String[] sortWord() {
List<Map.Entry<String, Integer>> wordlist = new ArrayList<Map.Entry<String, Integer>>(wordMap.entrySet());
Collections.sort(wordlist, ((o1, o2) -> o2.getValue().compareTo(o1.getValue()))); //排序
String[] str=new String[10];
int i=0;
for (Map.Entry<String, Integer> entry : wordlist) {
//拼接字符串key+value
if(i!=10) {
str[i]="<"+entry.getKey()+">"+":"+entry.getValue();
i++;
}
else {
break;
}
}
return str;
}
5、写出文件
利用FileWrite进行写出操作。
//path:写出文件的路径;content:写出的内容
public static void writetofile(String path, String content) throws IOException {
FileWriter fw = new FileWriter(new File(path));
fw.write(content);
fw.write("\n");
fw.close();
}
5、单元测试
对于各个功能模块分别提供一些测试样例进行测试。其中功能可基本实现。但写出文件模块无法将结果完成写出,每次都只能显示一个。
测试样例有:
代码覆盖率:
6、效能分析
利用JProfiler
7.结合在构建之法中学习到的相关内容与个人项目的实践经历,撰写解决项目的心路历程与收获。
答:
- 本次的作业对于编程不太好的我来说是一个挑战。由于个人能力有限,花费了很多时间在设计和实现代码,耗时也费力,只能实现简单的统计字符和行数的功能,效律低下。在网上查询了很多类似题目的代码,繁杂且难以吸收化为己用,同时我也请教同学,在其帮助下,我才能克服情绪化,完成这次的作业。
- 这次的作业更多的是让我们亲身感受学习软件工程中的一些重要思想。如错误处理并设计单元测试、效能分析、接口封装、psp等。这些可以更好的帮助程序员和团队完成软件的开发。一个完整的项目解决,一定要先思考分析完整后,再进行动手,不然会得不偿失,反而花费更多时间。以后的项目开发一定要流程规范。
- 在阅读构建之法的时候,书中提出了一系列程序员存在的问题。从自己身上看,发现这些问题在自己身上经常出现。编码前,只是查阅一下网上的资料稍作思考,直接就开始打代码。没有构思的过程,写出的程序很乱,经常会出现错误,将很多时间花在不必要的小错误上。当然我编写的程序仍存在着很多不尽如人意的地方,测试和代码设计也有一定的缺憾和漏洞,这些都是我在今后学习中要去学习改进的地方。