VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • 软工实践寒假作业(2/2)

这个作业属于哪个课程 软工
这个作业要求在哪里 作业要求
这个作业的目标 设计、开发一个疫情统计的程序、学习对程序的优化、学习GitHub的使用、PSP(个人软件开发流程)的学习使用、《构建之法》的学习
作业正文 作业
其他参考文献 Eclipse单元测试 JProfiler使用 github 博客园相关文章...

一、GitHub仓库地址

GItHub仓库地址

二、构建之法学习成果

2.PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 45
Estimate 估计这个任务需要多少时间 30 45
Development 开发 450 500
Analysis 需求分析 (包括学习新技术) 30 15
Design Spec 生成设计文档 30 25
Design Review 设计复审 30 35
Coding Standard 代码规范 (为目前的开发制定合适的规范) 45 60
Design 具体设计 30 50
Coding 具体编码 300 450
Code Review 代码复审 60 60
Test 测试(自我测试,修改代码,提交修改) 150 40
Reporting 报告 60 135
Test Repor 测试报告 60 90
Size Measurement 计算工作量 15 15
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 40
  合计 1350 1605

三、解题思路描述

1.所需知识点

本次任务我打算使用java语言,看到这个题目以后我想到了以下几个知识点需要被使用到

命令行参数的获取

在命令行中用户输入的参数,即list命令及其所带选项需要被程序读入并且正确处理
于是我找寻了相关的知识点如何获取java程序的命令行参数
并且编写了测试程序确保能够正确获取到命令行参数

文件的读入与输出

我们需要通过读取/log目录下的文件并且对其正确处理后将结果输出
这就涉及到java对文件输入输出的管理以及一些需要注意的细节(如编码问题)
java文件读写

2.选取正确的数据结构

仔细读取题目可以发现可以将每一个省定义为一个对象,即可定义Province类,该类拥有如下数据成员

/*记录一个省的各项数据*/
class Province{
    String name; /*省名*/
    int infect; /*感染人数*/
    int seeming; /*疑似人数*/
    int dead; /*死亡人数*/
    int cured; /*治愈人数*/

public Province() {
	infect = seeming = dead = cured = 0;
}

}

3.定义文件结构

221701126(目录名为学号)
  \--src
    \--InfectStatistic.java
    \--Lib.java
  \--README.md
    描述你的项目,包括如何运行、功能简介、作业链接、博客链接等
  \--codestyle.md
    描述你之前定的代码风格

4.代码风格制定

编写代码前肯定需要规范自己的代码风格,这关系编程过程中的代码样式,故参考了所给的阿里巴巴的java代码风格推荐,制定了属于自己的代码风格

5.需求分析

能够统计统计文件内信息并打印出需要了解的内容到目标文件中

1.根据命令行处理参数
2.选出目标目录下合适的文件
3.对每个文件的每行字符串进行处理,并记录数据
4.输出要求的行到目标文件

6.文件中字符串类型

分为以下几种:

<省> 新增 感染患者 n人
<省> 新增 疑似患者 n人
<省1> 感染患者 流入 <省2> n人
<省1> 疑似患者 流入 <省2> n人
<省> 死亡 n人
<省> 治愈 n人
<省> 疑似患者 确诊感染 n人
<省> 排除 疑似患者 n人

7.处理文件

看到文件结构就可以想到应该逐行处理,那么需要将字符串以空格分割成数组,更方便。接着可以知道第一个字符串是省份,可以存起来,最后应该字符串是人数,可以取出,中间的字符串就是行为,我们可以一个一个判断,遇到可以直接判断的字符串,就直接进行处理,不然就判断下一个字符串,再综合判断其行为,这样整个逻辑的判断就十分清晰了。

8.输出文件

先将所有省份按首字母顺序存放到一个数组,接着遍历数组,对每个省份进行判断是否要输出,如若需要输出,再将其作为参数传入相应的方法,再做具体判断。接着该方法中会进行type province选项参数的判定。

四、设计实现过程

代码流程

具体开发过程(逐步实现)

五、代码说明

1.数据结构

数据结构采用Province,封装了省名以及各项指标数据,如感染人数、疑似患者等,使用其即可表示单独一个省的情况。

class Province{
  String name; /*省名*/
  int infect; /*感染人数*/
  int seeming; /*疑似人数*/
  int dead; /*死亡人数*/
  int cured; /*治愈人数*/
  
  public Province() {
    infect = seeming = dead = cured = 0;
  }
}

2.处理命令行参数

获取args的参数,对args数组的数据进行处理
如果是-log命令,则存储输入路径
如果是-out命令,则存储输出路径
如果是-date命令,则存储日期
如果是-type命令,则存储type选项
如果是-province命令,则存储province选项

public static void solveArgs(String[] args) {
  int i = 0;
  int pos = 1;
  while(pos < args.length) {
    String arg = args[pos];
  //	System.out.println(pos + "-" + arg);
    if(arg.indexOf('-') == 0) {//这是命令
      
        if(arg.equals("-log")) {//处理输入路径
          inputPath = args[pos + 1] + "\\";
          pos+=2;
        }
        else if(arg.equals("-out")) {//处理输出路径
          outputPath = args[pos + 1] + "\\";
          pos+=2;
        }
        else if(arg.equals("-date")) {//处理日期
          targetDate = args[pos + 1];
          pos+=2;
        }
        else if(arg.equals("-type")) {
          for(i = pos + 1; i < args.length; i++) {
            String param = args[i];
            if(param.indexOf('-') != 0) {//这是参数
              typeItem.add(param);
            }
            else {
              pos = i;
              break;
            }
          }
        }
        else if(arg.equals("-province")) {//处理province命令
          for(i = pos + 1; i < args.length; i++) {
            String param = args[i];
            if(param.indexOf('-') != 0) {//这是参数
              provinceItem.add(param);
            }
            else {
              pos = i;
              break;
            }
          }
        }
        if(i == args.length) {
          break;
        }
      }
  }
}

以下展示用于存储各项数据的数据成员

public static String inputPath = "C:\\Users\\Peter\\Documents\\GitHub\\InfectStatistic-main\\221701126\\log\\";
public static String outputPath = "C:\\Users\\Peter\\Documents\\GitHub\\InfectStatistic-main\\221701126\\result\\out.txt";
public static String targetDate = "";
public static ArrayList<String> typeItem = new ArrayList<String>();/*记录type命令所带的选项*/
public static ArrayList<String> provinceItem = new ArrayList<String>();/*记录province命令所带的选项*/

3.寻找需要处理的文件

用一个vector来存储需要处理的文件,对目录下每一文件进行判断,若其日期小于命令行获取的date参数,则进入vector中存储
比较算法则是采用字符串的compareTo,即将文件名转化成字符串,接着进行判断
最后再放入“全国”

public static void solveDateOrder(String targetDate) {
  String maxDate = getMaxDate();
  if(targetDate.compareTo(maxDate) > 0) {
    System.out.println("日期超出范围");
    return;
  }
  //获取输入路径下的所有文件
  File file = new File(inputPath);
  if(file.isDirectory()) {
    Vector<String> toHandleDate = new Vector<String>();//获取符合要求待处理的日期文件
    String[] fileNames = file.list(); // 获得目录下的所有文件的文件名
    for(String fileName : fileNames) {
      fileName = fileName.substring(0, fileName.indexOf('.'));//截断后缀名
      //日期比较
      if(fileName.compareTo(targetDate) <= 0) {
        toHandleDate.add(fileName);
        System.out.println(fileName);
      }
      else {
        break;
      }
      //System.out.println(fileName);
    }

    if(toHandleDate.size() > 0) {
      solveEveryFile(toHandleDate);
    }
    map.put("全国", country);
  }
}

4.处理每个文件

对每个文件都逐行获取,接着使用字符串的split函数对其按空格进行分割,即可得到information数组

String[] information = str.split("\\s+");

关键算法:判断第二个字符串是什么
若是新增,则判断第三个字符串是感染患者还是疑似患者,进行数据统计

switch (information[1]) {
case "新增":
  if(information[2].equals("感染患者")) {//感染患者的情况
    p.infect += number;
    country.infect += number;
    //System.out.println(num);
  }
  else {//疑似患者的情况
    p.seeming += number;
    country.seeming += number;
  }
  break;

若是“感染患者”,则断定为感染者流入情况,则取出流入的省份已经人数进行数据处理

case "感染患者":
String p2 = information[3];//取出流入的省份名称
if(map.get(p2) != null) {//若该省份已经出现过
  Province anotherProvince = map.get(p2);
  anotherProvince.infect += number;
  p.infect -= number;
}
else {
  Province province2 = new Province();
  province2.name = p2;
  province2.infect += number;
  p.infect -= number;
  map.put(p2, province2);
}
break;

若是“疑似患者”,则判断是确诊还是流入,若为确诊,则减少疑似人数,增加感染人数,若为流入,如上处理

case "疑似患者":
//判断是流入还是确诊
if(information[2].equals("流入")) {
  String p3 = information[3];//取出流入的省份名称
  if(map.get(p3) != null) {//若该省份已经出现过
    Province anotherProvince = map.get(p3);
    anotherProvince.seeming += number;
    p.seeming -= number;
  }
  else {
    Province province3 = new Province();
    province3.name = p3;
    province3.infect += number;
    p.infect -= number;
    map.put(p3, province3);
  }
}
else {//确诊
  p.infect += number;
  p.seeming -= number;
  country.infect += number;
  country.seeming -= number;
}
break;

若为“死亡”,则减少感染人数,增加死亡人数

case "死亡":
p.infect -= number;
p.dead += number;
country.infect -= number;
country.dead += number;
break;

若为“治愈”,则减少感染人数,增加治愈人数

case "治愈":
p.infect -= number;
p.cured += number;
country.infect -= number;
country.cured += number;
break;

若为“排除”,则减少疑似人数

case "排除":
p.seeming -= number;
country.seeming -= number;
break;

5.获取各行人数

通过substring来截取到“人”的下标之前的子串

public static int getNumber(String[] information) {
	//获取人数
	String numString = information[information.length - 1];
	int index = numString.indexOf("人");
	numString = numString.substring(0, index);
	int number = Integer.parseInt(numString);
	return number;
}

6.打印结果

事先按顺序存储所有的省份

public static String[] province = {"全国", "安徽", "北京", "重庆", "福建", "甘肃", "广东", "广西", "贵州", "海南", "河北",
		"河南", "黑龙江", "湖北", "湖南", "吉林", "江苏", "江西", "辽宁", "内蒙古", "宁夏", "青海", "山东", "山西", "陕西",
		"上海", "四川", "天津", "西藏", "新疆", "云南", "浙江"
};

通过for循环来判断每一个省,看看是否需要输出

public static void printResult() {
	try {
		File output = new File(outputPath);
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(output));
		if(provinceItem.size() == 0) {
			for(String provinceName : province) {
				if(map.get(provinceName) != null) {
					printTheProvince(provinceName, osw);
				}
			}
		}
		else {
			for(String provinceName : province) {
				if(provinceItem.contains(provinceName)) {
					printTheProvince(provinceName, osw);
				}
			}
		}
		
		osw.flush();
		osw.close();
	} catch (IOException e) {
	}
}

7.对每个省的判断


相关教程