201621123053 张雨阳软工作业3
1.码云项目地址
https://gitee.com/milan_kaka/PairProject-Java
搭档项目和码云地址:
学号 201621123086:
https://www.cnblogs.com/piraat/p/9754497.html
https://gitee.com/piraat/PairProject-C/tree/master
2.PSP表格
PSP | 结对开发流程 | 预估耗费时间(分钟) | 实际耗费时间(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 900 |
· Estimate | 明确需求和其他相关因素,估计每个阶段的时间成本 | 20 | 40 |
Development | 开发 | 300 | 380 |
· Analysis | 需求分析 (包括学习新技术) | 60 | 60 |
· Design Spec | 生成设计文档 | 30 | 30 |
· Design Review | 设计复审 | 30 | 30 |
· Coding Standard | 代码规范 | 15 | 15 |
· Design | 具体设计 | 120 | 100 |
· Coding | 具体编码 | 180 | 100 |
· Code Review | 代码复审 | 30 | 30 |
· Test | 测试(自我测试,修改代码,提交修改) | 100 | 160 |
Reporting | 报告 | 60 | 60 |
· | 测试报告 | 30 | 120 |
· | 计算工作量 | 10 | 10 |
· | 并提出过程改进计划 | 20 | 20 |
3.解题思路描述
需求提升,需要新增三个功能。
- -m 查找词频为m的词组。
- -n 查找出现最n大的词语。
- -o 将输出结果写入文件output.txt。
- -i 打开文件。
除第一个功能外,其他三个功能可以在原有基础上改动。比如-n功能可以在输出时增加一个循环,循环输出排序好的HashMap。
4.设计实现过程
- -m 功能在WordCounter中新建了类 public Map getM(int m);。
- -n 功能的实现是在输出时将排序好的HashMap循环n次输出。
- -o 功能是原有功能。
- -i 只要将命令后的文件名提取就可以,其余和之前功能一样。
5.代码说明
(1)、新增功能类 public Map getM(int m);
public Map getM(int m){
wordFreq1 = new HashMap<String, Integer>();// 词频为m的词组
String t = text;
String[] str = t.split("\\s");
for (int i = 0; i < str.length-m+1; i++) {
String word = "";
int temp = 1;
for(int j = i; j< i+m ; j++ ){
if (str[j].length() < 4) { // 判断长度是否大于等于4
temp = 0;
break;
} else {
int flag = 1; // 判断字符串的前四位是否是英文字母
char a;
for (int k = 0; k < 4; k++) {
a = str[j].charAt(k);
if (!(a >= 'A' && a <= 'Z' || a >= 'a' && a <= 'z')) {
flag = 0;
}
}
if(flag==0){
temp = 0;
break;
}
else{
word = word + str[j] + " ";
}
}
}
if (temp == 1 && word.trim().length() != 0) {
if (wordFreq1.get(word.trim()) == null) { // 判断之前Map中是否出现过该字符串
wordFreq1.put(word.trim(), 1);
} else
wordFreq1.put(word.trim(), wordFreq1.get(word.trim()) + 1);
}
}
return wordFreq1;
}
原来是直接判断是否为单词,如果是单词就输入进Map中。现在多增加一个循环,如果单词就将其添加到word中,m次后将word输入进Map中。然后置word=""。一共要循环单词总数-m+1词,这时所有词频为m单词就全部输入进Map里面了。可以利用之前构造的函数对其排序。
(2)、主函数
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String[] command=str.split("\\s+");
FileDeal fd = new FileDeal();
String[] wFreq;
String[] wFreqM;
List sortMap;
List sortMapM;
String file=null;
int m=0;
int n=0;
String out=null;
int len=command.length;
for(int i=0;i<len;i++){
if(command[i].equals("-i")){
file=command[i+1];
}
if(command[i].equals("-m")){
m=Integer.parseInt(command[i+1]);
}
if(command[i].equals("-n")){
n=Integer.parseInt(command[i+1]);
}
if(command[i].equals("-o")){
out=command[i+1];
}
}
String text = fd.FileToString(file);
WordCounter wd = new WordCounter(text);
// 调用类中的方法获取相应的数值
int charNum = wd.getCharCount();
int wordCount = wd.getWordCount();
int ValidLine = wd.getLineCount();
Map<String, Integer> wordFreq = wd.getWordFreq();
sortMap = wd.sortMap(wordFreq);
wFreq = wd.ListToArray(sortMap);
String w = charNum + "\r\n" + wordCount + "\r\n" + ValidLine + "\r\n";
for (int i = 0; i < wFreq.length; i++) {
w = w + wFreq[i] + "\r\n";
}
if(m!=0){
Map<String, Integer> wordFreqM = wd.getM(m);
sortMapM = wd.sortMap(wordFreqM);
wFreqM = wd.ListToArray(sortMapM);
for(int i=0;i<wFreqM.length;i++){
System.out.println(wFreqM[i]);
}
}
if(n!=0){
for(int i=0; i<n; i++){
System.out.println(wFreq[i]);
}
}
if(out!=null){
fd.WriteToFile(w);
}
}
}
主函数需要将功能模块(-i,-m之类的)和语句(如输入的m,文件名input.txt)等分割开。这里我用字符串数组取出来,进行判断。但是这样有个缺点就是一旦命令行输入错误会直接导致程序崩溃。
之后就是调用各个部分的功能函数进行运算了。
截图
-m
-n -o
(3)、图形界面:
package WordCount;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.awt.event.ActionEvent;
import javax.swing.JTextPane;
import javax.swing.JTextArea;
public class JF extends JFrame {
private JPanel contentPane;
private JTextField textField;
public String str;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JF frame = new JF();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public JF() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
textField = new JTextField();
textField.setBounds(65, 54, 141, 41);
contentPane.add(textField);
textField.setColumns(10);
JTextArea textArea = new JTextArea();
textArea.setColumns(5);
textArea.setBounds(65, 110, 268, 119);
contentPane.add(textArea);
JButton btnNewButton = new JButton("上传");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String str = textField.getText();
String[] command=str.split("\\s+");
FileDeal fd = new FileDeal();
String[] wFreq;
String[] wFreqM;
List sortMap;
List sortMapM;
String file=null;
int m=0;
int n=0;
String out=null;
int len=command.length;
for(int i=0;i<len;i++){
if(command[i].equals("-i")){
file=command[i+1];
}
if(command[i].equals("-m")){
m=Integer.parseInt(command[i+1]);
}
if(command[i].equals("-n")){
n=Integer.parseInt(command[i+1]);
}
if(command[i].equals("-o")){
out=command[i+1];
}
}
String text = null;
try {
text = fd.FileToString(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
WordCounter wd = new WordCounter(text);
// 调用类中的方法获取相应的数值
int charNum = wd.getCharCount();
int wordCount = wd.getWordCount();
int ValidLine = wd.getLineCount();
Map<String, Integer> wordFreq = wd.getWordFreq();
sortMap = wd.sortMap(wordFreq);
wFreq = wd.ListToArray(sortMap);
String w = charNum + "\r\n" + wordCount + "\r\n" + ValidLine + "\r\n";
for (int i = 0; i < wFreq.length; i++) {
w = w + wFreq[i] + "\r\n";
}
if(m!=0){
Map<String, Integer> wordFreqM = wd.getM(m);
sortMapM = wd.sortMap(wordFreqM);
wFreqM = wd.ListToArray(sortMapM);
String w1 = "";
for(int i=0;i<wFreqM.length;i++){
w1 = w1 + wFreqM[i] + "\r\n";
}
textArea.setText(w1);
}
if(n!=0){
String w1 = "";
for(int i=0; i<n; i++){
w1 = w1 + wFreq[i] + "\r\n";
}
textArea.setText(w1);
}
if(out!=null){
try {
fd.WriteToFile(w);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
btnNewButton.setBounds(223, 54, 108, 41);
contentPane.add(btnNewButton);
}
}
图形界面做的比较简单,就是从文本框输入进命令,然后点击提交,在下面的输出结果栏显示输出结果。
6.单元测试
7.效能分析
8. 实验小结
- 这次时间跨度有点长,因为和搭档不是特别的熟悉,本来准备自己写一点,国庆的时候在一起讨论。但是我母亲做了一趟手术,国庆回了一次家。所以两个人基本是在网上完成讨论的,所以代码有很多不一样的地方。效果就我个人而言不是特别的理想。这是我个人的原因。
- 关于这次实验,之前没有想到String 能直接用+来运算,一直想用StringBuilder来做,但是这方面没学好,一直出错。问了同学才发现可以直接+,简便很多。
- 单元测试和效能分析还是有错,感觉是单元测试代码的问题,和我本身的代码没有关系。效能测试则是一打开程序就自动退出。这个就可能是程序本身的代码出错了。准备之后找同学要一下他们的代码学习一下。
- 关于图形界面,其实本来想做一个更像程序的界面,就是直接点击按钮就可以执行功能而不是还需要自己去输入命令。但是国庆从家里赶回来时间比较紧,只做了一个简单的GUI。