福大软工1816 · 第二次作业
github 地址:传不了,2kb/s 我传到明年好不好
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 12 |
· Estimate | · 估计这个任务需要多少时间 | 10 | 12 |
Development | 开发 | 135 | 196 |
· Analysis | · 需求分析 (包括学习新技术) | 15 | 28 |
· Design Spec | · 生成设计文档 | 0 | 0 |
· Design Review | · 设计复审 | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 20 |
· Design | · 具体设计 | 20 | 30 |
· Coding | · 具体编码 | 60 | 80 |
· Code Review | · 代码复审 | 10 | 8 |
· Test | · 测试(自我测试,修改代码,提交修改) | 20 | 30 |
Reporting | 报告 | 3 | 3 |
· Test Repor | · 测试报告 | 1 | 1 |
· Size Measurement | · 计算工作量 | 1 | 1 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 1 | 1 |
| | 合计 |148 |211
-
解题思路描述:
-
一开始看到这个题目,我内心是拒绝的,我不能说用Visual Studio Community 2017就用Visual Studio Community 2017,因为我没有windows。那只能用java了,而我java更加不熟练,大部分语句都是三年前学的几乎已经忘光了。所以我只好先看看java怎么写 = = 碰巧电脑里面保存了很早之前编写过的java代码,于是直接就可以开始了。
-
首先创建一个主程序类,用于io流的输入和输出。
-
其次创建一个计算类,用于分析读入的文本。
-
由于无视大小写字母,且输出为小写模式,因此应把读入的字符串全部转为小写方便操作。
-
统计文件字符数,因为不需要统计汉字,于是遍历字符串,计算其Ascal码小于178的总数。
-
统计单词总数,创建一个过程,遍历字符串。由于需要至少四个英文字母开头,计数开头英文字母数量,当开头字母数量为4以上,并且读到分隔符,单词数加加。
-
有效行数,读入文件时一行一行读入,字符串为空的跳过即可。
-
统计单词出现次数,运用哈希表存储,方便代码编写,最后对其排序输出。
-
-
设计实现过程:
-
代码设计为两个类,分别为 main 和 St。
-
main 类作为主程序使用。
-
调用java.io库在main内实现对input.txt的读入,和result.txt的输出。
-
把得到的字符串传递至St类进行分析。
-
调用St类内的函数,得到分析完成的答案。
-
-
St 类用于分析得到的字符串。
-
过程getS(String)用于从主程序得到目标字符串,将字符串英文字母转为小写,并调用分析过程St1(),St2()。
-
过程St1() 用于计算字符串内字符数,仅计算ascal码小于178的字符,由getS(String)调用。
-
过程St2()用于计算字符串内单词数量,并调用wordPush(String)过程,传递单词。
-
过程wordPush(String) 把得到的单词压入哈希表,统计每个单词出现次数。
-
函数outWordN() 把哈希表复制给List排序后,函数返回输出答案的字符串。
-
函数outsl() 和 outws() 分别返回字符数和单词数 的输出答案。
-
-
-
程序改进:
-
写完就这样,我觉得挺好的,不用改
-
「 VS 2017的性能分析工具 」是什么?
-
-
代码说明:
-
I/O流输入输出。百度了一下,借用了别人的程序进行修改 https://www.cnblogs.com/pyj03/p/7699113.html
St begin =new St(); // 这里创建一个新 St()类!!!! try { // 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw /* 读入TXT文件 */ String pathname = "./src/input.txt"; // 绝对路径或相对路径都可以,这里是绝对路径,写入文件时演示相对路径 File filename = new File(pathname); // 要读取以上路径的input。txt文件 InputStreamReader reader = new InputStreamReader( new FileInputStream(filename)); // 建立一个输入流对象reader br = new BufferedReader(reader); String line = ""; for (line=br.readLine();line!=null; line=br.readLine()){ begin.getS(line); //把输入流得到的字符串传给St类 if (line.length()>0) ko++; // 不记录空行 } /* 写入Txt文件 */ File writename = new File("./src/result.txt"); // 相对路径,如果没有则要建立一个新的output。txt文件 writename.createNewFile(); // 创建新文件 BufferedWriter out = new BufferedWriter(new FileWriter(writename)); out.write(begin.outsl()+"\r\n"); //输出字符数 out.write(begin.outws()+"\r\n"); //输出单词数 out.write("lines: "+String.valueOf(ko)+"\r\n"); //输出行数 out.write(begin.outWordN()); //输出排序后的单词 out.flush(); // 把缓存区内容压入文件 out.close(); // 最后记得关闭文件 } catch (Exception e) { e.printStackTrace(); }
}
```-
St1(),统计字符数,由于ascal码大多数在178以内,而汉字通常很大,所以只统计178以内数量
public void st1(){ for(int i=0;i<s.length();i++){ char ch = s.charAt(i); int j=(int)ch; if (j<178) sl++; }
}
```-
St2(),统计单词数,函数syadann(int)返回boolean,判断是否为分隔符,函数eigo(int)返回boolean,判断是否为英文字母。
public void st2(){ int k=0; //单词前英文字母数量 boolean ikeru=true; //字符是否暂时只出现英文字母 String th=""; // th 用于记录这个单词 for(int i=0;i<s.length();i++){ char ch = s.charAt(i); int j=(int)ch; if (!syadann(j)){ th=th+ch; } // 不是分隔符便记录 if (ikeru && eigo(j)){ k++; // 出现的英文字母加 1 }else if (ikeru && !eigo(j)) ikeru=false; //单词间出现了非英文字母字符 if (syadann(j) || i==s.length()-1) { if (k>=4) { //此单词开头出现了大于4个的英文字母,符合单词构成 ws++; wordPush(th); //把单词放入wordPush()过程内 } ikeru=true; k=0; th=""; } }
}
```-
wordPush(String) ,把从St2()过程得到的符合单词规则的单词,压入哈希表,已存在 则记录个数加1
private void wordPush(String sk) { if(wordSet.contains(sk)) { Integer number=hashMap.get(sk); number++; hashMap.put(sk, number); } else { hashMap.put(sk, 1); }
}
```-
函数outWordN() 返回答案字符串。通过查询得知Collections.sort排序只能用于list,所以创建两个List 来存放哈希表的内容。由于快速排序有点不太记得,就暴力地排序了两遍,把已经按字典序排序的list里面按顺序,把前十个出现次数最多的数抽出来。
public String outWordN(){ String kk=""; List<String> list=new ArrayList<String>(wordSet); List<Integer> list2=new ArrayList<Integer>(); Collections.sort(list); for(int i=0;i<list.size();i++) list2.add(hashMap.get(list.get(i))); Collections.sort(list2); for (int j=1; j<=10; j++) for (int i=0;i<list.size();i++){ if (hashMap.get(list.get(i))==list2.get(list2.size()-j)){ kk=kk+"<"+list.get(i)+">: "+hashMap.get(list.get(i))+"\r\n"; list.remove(i); break; } } return kk;
}
``` -
-
样例
-
1 http://www.en8848.com.cn/tingli/meiwen/xgnysbds48/212321.html
characters: 2731 words: 274 lines: 32 <rain>: 10 <through>: 9 <said>: 7 <they>: 7 <take>: 6 <this>: 6 <away>: 5 <time>: 5 <their>: 4 <what>: 4
-
2 http://www.en8848.com.cn/tingli/meiwen/xgnysbds48/212188.html
characters: 1564 words: 158 lines: 44 <teach>: 9 <world>: 5 <that>: 4 <been>: 3 <every>: 3 <gently>: 3 <going>: 3 <have>: 3 <there>: 3 <will>: 3
-
-
源代码之main 类
import java.io.*;
public class main {
private static int ko=0;
private static BufferedReader br;
public static void main(String[] args) {
St begin =new St();
try { // 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw
/* 读入TXT文件 */
String pathname = "./src/input.txt"; // 绝对路径或相对路径都可以,这里是绝对路径,写入文件时演示相对路径
File filename = new File(pathname); // 要读取以上路径的input。txt文件
InputStreamReader reader = new InputStreamReader(
new FileInputStream(filename)); // 建立一个输入流对象reader
br = new BufferedReader(reader);
String line = "";
for (line=br.readLine();line!=null; line=br.readLine()){
begin.getS(line);
if (line.length()>0) ko++;
}
/* 写入Txt文件 */
File writename = new File("./src/result.txt"); // 相对路径,如果没有则要建立一个新的output。txt文件
writename.createNewFile(); // 创建新文件
BufferedWriter out = new BufferedWriter(new FileWriter(writename));
out.write(begin.outsl()+"\r\n");
out.write(begin.outws()+"\r\n");
out.write("lines: "+String.valueOf(ko)+"\r\n");
out.write(begin.outWordN());
out.flush(); // 把缓存区内容压入文件
out.close(); // 最后记得关闭文件
} catch (Exception e) {
e.printStackTrace();
}
}
}
-
源代码之St类
import java.util.*;
public class St {
private static String s;
private static int sl=0;
private static int ws=0;
private HashMap<String, Integer > hashMap=new HashMap<String,Integer>();
private Set<String> wordSet=hashMap.keySet();
public String outsl(){ return "characters: "+String.valueOf(sl); }
public String outws(){ return "words: "+String.valueOf(ws); }
public String outWordN(){
String kk="";
List<String> list=new ArrayList<String>(wordSet);
List<Integer> list2=new ArrayList<Integer>();
Collections.sort(list);
for(int i=0;i<list.size();i++) list2.add(hashMap.get(list.get(i)));
Collections.sort(list2);
for (int j=1; j<=10; j++)
for (int i=0;i<list.size();i++){
if (hashMap.get(list.get(i))==list2.get(list2.size()-j)){
kk=kk+"<"+list.get(i)+">: "+hashMap.get(list.get(i))+"\r\n";
list.remove(i);
break;
}
}
return kk;
}
public boolean syadann(int c){
if (c>=48 && c<=57) return false;
if (c>=65 && c<=90) return false;
if (c>=97 && c<=122) return false;
return true;
}
public boolean eigo(int c){
if (c>=65 && c<=90) return true;
if (c>=97 && c<=122) return true;
return false;
}
public void getS(String s){
if (s!=null){
St.s=s.toLowerCase();
st1();
st2();
}
}
private void wordPush(String sk) {
if(wordSet.contains(sk))
{
Integer number=hashMap.get(sk);
number++;
hashMap.put(sk, number);
}
else
{
hashMap.put(sk, 1);
}
}
public void st1(){
for(int i=0;i<s.length();i++){
char ch = s.charAt(i);
int j=(int)ch;
if (j<178) sl++;
}
}
public void st2(){
int k=0;
boolean ikeru=true;
String th="";
for(int i=0;i<s.length();i++){
char ch = s.charAt(i);
int j=(int)ch;
if (!syadann(j)){
th=th+ch;
}
if (ikeru && eigo(j)){
k++;
}else if (ikeru && !eigo(j)) ikeru=false;
if (syadann(j) || i==s.length()-1) {
if (k>=4) {
ws++;
wordPush(th);
}
ikeru=true;
k=0;
th="";
}
}
}
}