软工作业三
要求地址
PSP表格
PSP2.1 | 个人开发流程 | 预估耗费时间(分钟) | 实际耗费时间(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 7 |
· Estimate | 明确需求和其他相关因素,估计每个阶段的时间成本 | 10 | 7 |
Development | 开发 | 275 | 240 |
· Analysis | 需求分析 (包括学习新技术) | 40 | 35 |
· Design Spec | 生成设计文档 | 10 | 10 |
· Design Review | 设计复审 | 5 | 5 |
· Coding Standard | 代码规范 | 10 | 10 |
· Design | 具体设计 | 30 | 20 |
· Coding | 具体编码 | 120 | 120 |
· Code Review | 代码复审 | 30 | 20 |
· Test | 测试(自我测试,修改代码,提交修改) | 30 | 20 |
Reporting | 报告 | 90 | 90 |
· | 测试报告 | 40 | 40 |
· | 计算工作量 | 20 | 20 |
· | 并提出过程改进计划 | 30 | 30 |
解题思路描述
在代码上,和小伙伴两个人的其实没有什么优劣之分。因为主要由我来实现新功能,所以两个人决定采用我的代码。
关于新增功能:
- 词组统计:首先将按行读取的字符串连接成一串字符串。通过正则表达式分割单词并放入字符数组中。从第一个单词开始计算以该单词为首的词组及其词频。
- 自定义输出:将上次作业中的Count类中的WordTop函数中加入参数n,将原来函数中定死的“10”改为参数n。
设计实现过程
一、相关类的设计
- File类:读取文件数据,写入数据到文件
- Count类:统计函数的实现
- Main类:其他类和函数的调用
二、相关函数的设计
1. File类:
- readfile函数:从文件中按行读取数据并保存到ArrayList中
- writefile函数:将统计得到的结果写入文件中
2. Count类:
- CountChars函数:统计文本字符数
- CountWords函数:统计文本合法单词数
- CountLine函数:统计文本合法行数
- WordTop函数:统计最多的10个单词及其词频
- CountPhrase函数:统计词组
代码说明
1. 实现命令行参数设定输入
String in=null; //初始化变量 String out=null; int m=0,n=0; for(int i=0;i<args.length;i++){ if("-i".equals(args[i])){ //若为“-i”,索引+1,将所带参数值赋值给in i++; in=args[i]; } if("-m".equals(args[i])){ //若为“-m”,索引+1,将所带参数值赋值给m i++; m=Integer.parseInt(args[i]); } if("-n".equals(args[i])){ //若为“-n”,索引+1,将所带参数值赋值给n i++; n=Integer.parseInt(args[i]); } if("-o".equals(args[i])){ //若为“-o”,索引+1,将所带参数值赋值给out i++; out=args[i]; } }
2. CountChars函数:
public int CountChars(){ //统计文本字符数 int count=0; for(int i=0;i<line.size();i++){ //遍历文本数据 String str=line.get(i); for(int j=0;j<str.length();j++){ //遍历每行字符串 char c=str.charAt(j); //转换成字符 if(('A'<=c&&c<='Z')||('a'<=c&&c<='z')||c=='\n'||c=='\r'||c=='\t'){ count++; //若为合法字符则计数 } } } return count; }
3. CountWords函数:
public int CountWords(){ //统计文本合法单词数 int count=0; for(int i=0;i<line.size();i++){ //遍历文本数据 String str=line.get(i); if(str.length()>=4){ //若该行字符串长度大于等于4,则该行可能存在合法单词 String[] words=str.split("[^a-zA-Z0-9]+"); //通过正则表达式匹配分隔符来分割字符串 for (String word:words){ //遍历分割后的字符串数组 int flag=0; //标识符标识是否为合法单词 char[] w=word.toCharArray(); for(int j=0;j<4;j++){ //遍历字符串数组的前四个字符 if(!(('A'<=w[j]&&w[j]<='Z')||('a'<=w[j]&&w[j]<='z'))){ flag=1; break; //若不为英文字母则标识符赋值为1并跳出循环 } } if(flag==0){ //若为合法单词 if(!map.containsKey(word)){ //该单词第一次出现 count++; //单词数加1 map.put(word, 1); //将键、值添加进map中 } else{ int num=map.get(word); //该单词已出现过 map.put(word, ++num); //单词词频加1 } } } } } return count; }
4. CountLine函数:
public int CountLine(){ //统计文本合法行数 int count=0; for(int i=0;i<line.size();i++){ //遍历文本数据 String str=line.get(i); if(str.length()>0){ //若该行字符串长度大于0,则计数 count++; } } return count; }
5. WordTop函数:
public ArrayList WordTop(int count){ //统计最多的10个单词及其词频 ArrayList<Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(map.entrySet()); //定义一个list来存放排序后的单词及其词频 Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { //重写比较器的排序函数 @Override public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) { if (o1.getValue() == o2.getValue()) { return o1.getKey().compareTo(o2.getKey()); } return o2.getValue() - o1.getValue(); } }); if(count<=10){ //若单词数不大于10,则直接返回排序后的list return list; } else{ //若单词数大于10,则将第10位以后的单词从list中移除再返回list for(int i=list.size();i>=10;i--){ list.remove(i); } return list; } }
6. CountPhrase函数:
public Map CountPhrase(int m){ //词组统计 String str=null; for(int i=0;i<line.size();i++){ //将按行读取得到的字符串列表连接成一串字符串 String s=line.get(i); if(i==0){ str=s; } else{ str=str+" "+s; } } System.out.println(str); String[] words=str.split("[^a-zA-Z0-9]+"); //通过正则表达式匹配分隔符来分割字符串 for (int i=0;i<words.length;i++){ //从每个分割出来的字符串开始计算词组 int flag=0; //定义标识符标识是否为单词 int p=i; //记录当前遍历的字符串索引 String s=words[p].toLowerCase(); if(map.containsKey(s)){ //若当前字符串为单词 String phrase=s; for(int j=1;j<m;j++){ //连接单词为词组 p++; if(((p)<words.length)&&(map.containsKey(words[p]))){ phrase=phrase+" "+words[p]; System.out.println(p); } else{ flag=1; //若连续单词个数不满足设定的词组则跳出循环 break; } } if(flag==0){ //将词组及其数量添加到map中 if(!map2.containsKey(phrase)){ map2.put(phrase, 1); } else{ int num=map2.get(phrase); map2.put(phrase, ++num); } } } } return map2; }
感受
这次结对编程我主要负责新增功能的实现。新增功能的实现并没有什么难度,主要是新增一个功能函数,以及对原有代码进行一些小更改。之前的代码里读入文件路径是定死的,确实是没有考虑到非代码编写者的使用感受。新增功能函数的实现上面已经有具体内容了,这里就不赘述了。因为个人比较喜欢开发这块,而且对于测试没有太大兴趣,队友恰好比较喜欢,两人一拍即合,愉快地分工,整个合作过程还是很融洽的。虽然国庆期间相隔两地,但还是坚持通过视频聊天等等手段完成本次作业,精神可嘉。
来源:https://www.cnblogs.com/holmec/p/9757033.html