Github仓库地址
shodowQAQ/InfectStatistic-main
PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
60 |
40 |
Estimate |
估计这个任务需要多少时间 |
60 |
40 |
Development |
开发 |
600 |
900 |
Analysis |
需求分析 (包括学习新技术) |
120 |
100 |
Design Spec |
生成设计文档 |
120 |
80 |
Design Review |
设计复审 |
60 |
40 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
60 |
30 |
Design |
具体设计 |
120 |
100 |
Coding |
具体编码 |
480 |
560 |
Code Review |
代码复审 |
60 |
40 |
Test |
测试(自我测试,修改代码,提交修改) |
60 |
50 |
Reporting |
报告 |
60 |
60 |
Test Repor |
测试报告 |
60 |
40 |
Size Measurement |
计算工作量 |
40 |
30 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
30 |
30 |
合计 |
1870 |
2140 |
|
解题思路
题目可以分为三部分:1.指令分解 2.文件的读写 3.字符串的处理
大前提:
先定好需要输出的数据。如:省份名字,每个省份有四种人,就定个二维数组与省份对应等等。
再定义标记数据。如:每个省份一个标记,判断该省份是否需要输出。
1.首先是指令分解:
有一说一这个真的难倒我了,以前写的java程序都是用的swing,写c++程序的界面也是用的 switch()不断刷新界面,第一次写这种需要拆分指令的程序。刚开始没思路,本来打算直接输入一个String然后对String进行解析。后来觉得这样做太复杂问了同学,同学给了他的解决思路,才改用现在的思路。即使用args生成的String[],有一个好处是用空格可以指令分开,这样就大大的简化了对指令的处理,把指令拆分开来进行对比。
首先是匹配-list,-date,-log,-out,这些指令。当匹配到这些指令之后在对这些指令后面的内容进行处理,判断输入的信息是否正确,符合要求。
2.文件的读写:
文件的读就是对日期进行比较,选择要读取的文件。
文件的写首先是基础版,即不带-province或-type,只要把所有的province的二维数组写出配合文字即可。
升级版就是给每一个type和province都建立一个与之对应的数组,当数组的值为0时写出,为1的时候掠过。
3.字符串的处理
这部分有用的正则表达式和字符串的函数,从文本中提取数字,判断文本的类型。
设计实现过程
1.基础数据
/*定义静态数据省份和数据*/
static String[] province = {"全国", "安徽", "澳门" ,"北京", "重庆", "福建","甘肃","广东", "广西", "贵州", "海南", "河北", "河南", "黑龙江", "湖北", "湖南", "吉林","江苏", "江西", "辽宁", "内蒙古", "宁夏", "青海", "山东", "山西", "陕西", "上海","四川", "台湾", "天津", "西藏", "香港", "新疆", "云南", "浙江"};
/*定义每个省份的四种数据*/
static int[][] data =new int[35][4];
/*定义需要输出的省份默认全为零即全输出*/
static int[] needprovince=new int[35];
/*定义时间*/
static String date;
/*定义输入路径*/
static String input;
/*定义输出路径*/
static String output;
/*定义需要输出的类型默认全为零即全输出*/
static int[] type = new int[4];
/*定义患者类型*/
static String[] typename = {"感染患者", "疑似患者", "治愈", "死亡"};
2.指令分解:
指令保存为String[] args,对每个args[i]判断,对于每种判断结果有不同的操作,-out和-log都对指令的值进行正则表达式匹配,然后值赋给output和input变量。-type对ip,sp,cure,dead进行匹配对type[]进行赋值,为0输出为1不输出。-province 对省份名字进行匹配,同样为零输出,为一不输出。
3.文件读取
在input路径下,先读入要读取的文件名称,对每个文件的每行进行读取,对每行的内容进行正则表达式匹配,当读到不同内容时进行不同处理,就是对int[][] data的数据进行加减,这部分简单,只要表达式判断正确就可以。
4.文件写入
我首先完成的是对所有的省份和类型的人都写入。只要省份加类型加数据写入就可以。
然后增加了-province和-type属性,在输出前对type[],和needprovince[]进行判断就可以。
代码说明
判断指令:
因为指令为String[],对指令进行匹配,匹配到相应的字符串就进行指令处理。处理结束后i++跳转到下一个指令。
public boolean checkInstructions() {//判断指令是否输入成功
if(instructions.length==0)
{
System.out.println("指令输入失败");
return false;
}
if(!instructions[0].equals("list")) {//判断命令格式是否正确
System.out.println("指令必须以list开头");
return false;
}
for (int i=0;i<instructions.length;i++)
{
if(instructions[i].equals("-date")) { //读取到-date参数
i = setDate(++i);
if(i == -1) { //说明上述步骤中发现命令行出错
System.out.println("日期输入格式错误");
return false;
}
}
else if(instructions[i].equals("-log")) {//读取-log输入路径
i = setInPut(++i);
if(i == -1) { //说明上述步骤中发现命令行出错
System.out.println("输入参数错误");
return false;
}
}
else if(instructions[i].equals("-out")) {//读取-out输出路径
i = setOutPut(++i);
if(i==-1) {
System.out.println("输出参数错误");
return false;
}
}
else if(instructions[i].equals("-type")) {//读取-type指令
i = setType(i++);
if(i==-1) {
System.out.println("type指令格式错误");
return false;
}
}
else if(instructions[i].equals("-province")) {//读取-province 指令
i =setNeedProvince(i++);
if (i==-1) {
System.out.println("province指令格式错误");
return false;
}
}
}
return true;
}
处理举例1:
setNeedProvince()
首先默认needprovince[]全为零是全输出,当检测到有-province时将所有置为1即都不输出,然后进行匹配。同时judge来判断是否有匹配,如果没有一个可以匹配就返回指令错误。
/*需要的省份数据*/
public int setNeedProvince(int i) {
int judge=0;//判断有无更改
for(int j = 0;j<35;j++) {//将所有定义为不输出
needprovince[j] = 1;
}
if(i < instructions.length) {
for(int j = 0;i < 35;j++) {
if (province[j].equals(instructions[i])) {
needprovince[j] = 0;
judge=1;
i++;
}
}
if(judge == 0) {
return -1;
}
}
else {
return -1;
}
return i;
}
处理举例2:
同上本身所有的type[]都为0都输出,检测到-type全置为1不输出,进行匹配将匹配到的重新置为0,如果没有匹配就返回错误。
/*指令输出数据类型*/
public int setType(int i) {
for(int j = 0;j<4;j++)//将所有类型定义为不输出
{
type[j] = 1;
}
if(i < instructions.length) {
if(instructions.equals("ip"))
{
type[0] = 0;
i++;
}
if(instructions.equals("sp")) {
type[1] =0;
i++;
}
if(instructions.equals("cure")) {
type[2] = 0;
i++;
}
if(instructions.equals("dead")) {
type[3] = 0;
i++;
}
if (type[0] == 1&&type[1] == 1&&type[2] == 1&&type[3] == 1) {
return -1;
}
}
else
return -1;
return i;
}
处理举例3:
正则表达式判断路径是否合理,如果不合理返回错误。
public int setOutPut(int i) {
if(i < instructions.length) {
if(instructions[i].matches("^[A-z]:\\\\(\\S+)+(\\.txt)$")) //判断字符串是不是txt文件路径
output = instructions[i];
else
return -1;
} else
return -1;
return i;
}
}
文件读取:
对读到的每行进行正则表达式匹配,选择处理方式。
public void readTxt(String filePath){
try {
int casenumber;
BufferedReader bfr = new BufferedReader(new InputStreamReader(
new FileInputStream(new File(filePath)), "UTF-8"));
String lineTxt = null;
while ((lineTxt = bfr.readLine()) != null) {
if(!lineTxt.startsWith("//"))
{
handleCase(lineTxt);
}
}
bfr.close();
writeTxt();
} catch (Exception e) {
e.printStackTrace();
}
}
匹配函数:
匹配后进行相应处理。
/*文本处理*/
public void handleCase(String string) {
String case1 = "(\\S+) 新增 感染患者 (\\d+)人";
String case2 = "(\\S+) 新增 疑似患者 (\\d+)人";
String case3 = "(\\S+) 治愈 (\\d+)人";
String case4 = "(\\S+) 死亡 (\\d+)人";
String case5 = "(\\S+) 感染患者 流入 (\\S+) (\\d+)人";
String case6 = "(\\S+) 疑似患者 流入 (\\S+) (\\d+)人";
String case7 = "(\\S+) 疑似患者 确诊感染 (\\d+)人";
String case8 = "(\\S+) 排除 疑似患者 (\\d+)人";
boolean isCase1 = Pattern.matches(case1, string);
boolean isCase2 = Pattern.matches(case2, string);
boolean isCase3 = Pattern.matches(case3, string);
boolean isCase4 = Pattern.matches(case4, string);
boolean isCase5 = Pattern.matches(case5, string);
boolean isCase6 = Pattern.matches(case6, string);
boolean isCase7 = Pattern.matches(case7, string);
boolean isCase8 = Pattern.matches(case8, string);
if(isCase1==true) {
addIP(string);
}
else if(isCase2==true) {
addSP(string);
}
else if(isCase3==true) {
addCure(string);
}
else if(isCase4==true) {
addDeath(string);
}
else if(isCase5==true) {
moveIP(string);
}
else if(isCase6==true) {
moveSP(string);
}
else if(isCase7==true) {
diagnoseSP(string);
}
else if(isCase8=true) {
ignoreSP(string);
}
}
处理举例(原理都一样举一例)
检测情况后对人前的数字进行读取。在对data二维数组进行修改
/*治愈患者处理*/
public void addCure(String string) {
String[] str_arr = string.split(" ");
int i;
int n = Integer.valueOf(str_arr[2].replace("人", ""));
for(i = 0; i < province.length; i++) {
if(str_arr[0].equals(province[i])) {
data[0][2] += n; //全国治愈人数增加
data[0][0] -= n; //全国感染患者人数减少
data[i][2] += n; //该省份治愈人数增加
data[i][0] -= n; //该省份感染患者人数减少
break;
}
}
}
文件写入
province[i]+typename[k]+data[i][k]进行写入。再写入前进行needprovince[i]和typr[k]进行判断是否需要写出。
public void writeTxt() {
FileWriter fwriter = null;
int i, j, k;
try {
fwriter = new FileWriter(output);
for(i = 0; i < province.length; i++) {
if(needprovince[i] == 0) {
fwriter.write(province[i] + " ");
for(k = 0; k < type.length; k++) {
if(type[k]==0)
fwriter.write(typename[k] + data[i][k] + "人 ");
}
fwriter.write("\n");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fwriter.flush();
fwriter.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
单元检测
2.
3.
4.
5.
6.
7.
8.
9.
10.
单元测试覆盖率优化和性能测试
git仓库链接、代码规范链接
新路历程和收获
这个作业真的是受益匪浅,全是现学现卖,本人一直是一只菜鸡,几乎没有开发过什么课外程序,只是单纯了完成老师的作业。以前写java程序要么是多线程,要么是jdbc,第一次对字符串进行处理。同时学会了设计指令,以前都是简单的switch()或者直接用图形界面。
刚开始看到作业的时候完全是蒙蔽的,指令系统没有一点思路,问了同学才知道了设计方法。同时因为对字符串处理完全没有经验,刚开始都想用数据库,把文本里的数据读到数据库里再输出,后来又一想用几个静态变量储存就好,然后实际写的过程中发现用静态变量还麻烦,不如直接把处理过程写成子类,这样可以直接用指令类里的数据。
等程序写了60%以后就轻松了,有了大体的思路,有很大一部分都代码都是重复之前的工作。
我就是老师说的d类程序员,给病人做手术时做一个,出去玩一下,回来接着做,导致我效率很低,没办法在预定时间完成任务。以后要改掉这个毛病。导致没有优化和覆盖率测试。
本来计划昨天写完的,结果在配置javaee的tomcat我怎么配置他都和eclipse联动不起来,chrome里面可以访问localhost,eclipse就404,换了四五个tomcat版本和java版本,浪费了一晚上加一天的时间都没装好,今天写完这个作业格式化一下c盘试试。
技术路线
- java拼车程序
这个是个重邮的一个学长写的毕设,本科毕业直接去阿里,年薪30w大佬啊,同时因为这是他学生时期写的,也很适合我借鉴学习。
- 会议管理系统
这个是一个程序员给java入门用的项目,会议管理系统,供刚入行的小伙伴学习,使用的技术比较基础。
- 博客系统
这个是基于ssm写的博客系统,也是一个毕业年薪20w的学长写的给刚入门的小伙伴练手。
- 一份涵盖大部分Java程序员所需要掌握的核心知识
这个是fork最多的java学习项目
- 完整的电商系统
这个看上去很难是个网上商城,这学期也选了javaee这门课,这不就联动起来了。