**
7-1 水文数据校验及处理 (50 分)
**
使用Java中的字符串处理类以及正则表达式对输入字符串数据进行合法性校验及计算。(具体需求参见附件 2021-OO第04次作业-1指导书V1.0.pdf )
输入格式:
假定分水口门的数据上报时是采用人工输入的方式,每一行代表一个整点时刻的分水数据,各数据之间采用“|”符号进行分隔,每次可以输入多条数据,直到遇到用户输入“exit”为止,每一行输入数据共包含五部分:测量时间、目标水位、实际水位、开度(包含目标开度和实际开度,以“/”分隔)、流量。 各数据格式要求如下:
测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分”始终保持两位,且始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
目标开度、实际开度:实型数,取值范围为[1,10),必须保留2位小数,两个开度之间用“/”分隔
输出格式:
对输入的数据进行有效性校验,其规则如前所述,如遇到不符合规则的数据,系统应能够给出错误提示,提示规则如下:
如果每一行输入数据不是由“|”分隔的五部分,则输出:
Wrong Format
Data:输入的数据
如果某一部分数据有误,则按如下方式显示:
Row:行号,Column:列号Wrong Format
Data:输入的数据
其中,行号为输入数的行数(从1开始),列号为6个数据的序号(从1开始,最大为6,顺序参见输入数据结构说明)
由于人工输入数据可能存在疏忽,在每一个输入数据两端均可能存在多余的空格,程序应该能够自动过滤这些空格(不报错)。
如果用户未输入数据,则直接输出Max Actual Water Level和Total Water Flow的值即可(均为0)
若输入无误,则对数据进行如下处理:
当实际开度的值大于目标开度时,程序给出如下警告:
Row:1 GateOpening Warning
求出所输入数据中的最大实际水位值(保留2位小数),输出格式如下: Max Actual Water Level:实际水位值
根据每个整点时刻的瞬时流量求出所输入的所有时段的总流量(保留2位小数),其计算公式为(参见作业指导书):
p
=
∑
n
=
1
N
2
∗
60
∗
60
∗
F
l
o
w
p = \sum_{n=1}^N2*60*60*Flow
p=n=1∑N2∗60∗60∗Flow
输出格式如下:
Total Water Flow:总流量值
解题报告
1.输入数据的校验一律采用正则表达式,尤其是测量日期的校验,可自行百度,一定要弄懂
2.认真研究指导书中给的类结构,思考CheckData、DealData两个类的作用
3.编写代码务必弄懂需求(指导书),务必做到严谨
输入样例1:
2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780
2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0
2015/8/2 8:00|133.830|133.070|1.11/1.11|73.890
2015/8/2 10:00|133.820|133.080|1.11/1.11|74.380
exit
输出样例1:
Row:1,Column:2Wrong Format
Data:2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780
Row:2,Column:4Wrong Format
Row:2,Column:6Wrong Format
Data:2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0
输入样例2:
2015/8/5 2:00|133.800|133.080|1.11/1.11|73.870
2015/8/5 4:00|133.800|133.070|1.11/1.11|73.330
2015/8/5 6:00|133.830|133.110|1.11/1.21|70.610
2015/8/5 8:00|133.860|133.140|1.11/1.11|73.430
2015/8/5 10:00|133.91|133.15|1.11/1.11|73.06
2015/8/5 12:00|133.900|133.110|1.16/1.11|75.460
2015/8/5 14:00|133.920|133.140|1.16/1.11|77.030
2015/8/5 16:00|133.92|133.16|1.16/1.91|79.4
2015/8/5 18:00|133.940|133.170|1.16/1.11|76.810
2015/8/5 20:00|133.94|133.19|1.16/1.11|74.53
2015/8/5 22:00|133.930|133.200|1.16/1.11|74.400
2015/8/6 0:00|133.930|133.200|1.16/1.11|73.150
2015/8/6 2:00|133.930|133.180|1.16/1.11|74.830
2015/8/6 4:00|133.910|133.180|1.16/1.11| 73.270
exit
输出样例2:
Row:3 GateOpening Warning
Row:8 GateOpening Warning
Max Actual Water Level:133.20
Total Water Flow:7510896.00
//有一个测试点没有通过!!!
import java.util.Scanner;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Scanner x = new Scanner(System.in);
StringBuilder a=new StringBuilder(x.nextLine());//输入数据给a
String a1=x.nextLine();
String exit="exit";
int i,h,flag,flag1=0;
double sum=0,max=0;
while (!a1.equals(exit)){
a.append('\n').append(a1);
a1=x.nextLine();//输入数据给a
}
String kp= String.valueOf(a);
String[] b =kp.split("\n");//把输入的数据根据行放在数组b里
Double[] sjsw =new Double[b.length];//创建实际水位的数组
Double[] ll =new Double[b.length];//创建流量数组
String time1= "(((([1-9])|([1-9][0-9])|([1-9][0-9]{2})|([1-9][0-9]{3})/((([13578]|1[02])/([1-9]|[12][0-9]|3[01]))|(([469]|11)/([1-9]|[12][0-9]|30))|(2/([1-9]|[1][0-9]|2[0-8])))))|(((([1-9][0-9])(0[48]|[2468][048]|[13579][26]))|(([48]|[2468][048]|[3579][26])00))/2/29)) ((([02468])|(1[02468])|(2[02])):00)";//匹配时间
String kp1="([1-9][0-9]{0,2}(\\.[0-9]{1,3})?)";//匹配水位和匹配流量
String kdkp="([1-9]\\.[0-9]{2})";//匹配开度
Pattern swll=Pattern.compile(kp1);
Pattern kd1=Pattern.compile(kdkp);
Pattern timekp=Pattern.compile(time1);
for (i=0,h=0;i<b.length;i++){//按照行循环
String[] hang =b[i].split("\\|");//每行通过|分隔成行数组
String[] kd =hang[3].split("\\/");//把每行的开度通过/分开存入开度数组里
String shijian1=hang[0].trim();//时间,去掉每一行输入的头尾的空格
String mbsw1=hang[1].trim();//目标水位,去掉每一行输入的头尾的空格
String sjsw1=hang[2].trim();//实际水位,去掉每一行输入的头尾的空格
String kaidu1=hang[3].trim();//开度,去掉每一行输入的头尾的空格
String liuliang1=hang[4].trim();//流量,去掉每一行输入的头尾的空格
String mbkd1=kd[0].trim();//目标开度,去掉每一行输入的头尾的空格
String sjkd1=kd[1].trim();//实际开度,去掉每一行输入的头尾的空格
flag=0;
if(!timekp.matcher(shijian1).matches()){//如果时间不合法
flag=1;flag1=1;
System.out.println("Row:"+(i+1)+",Column:1Wrong Format");
}
if(!swll.matcher(mbsw1).matches()){//如果目标水位不合法
flag=1;flag1=1;
System.out.println("Row:"+(i+1)+",Column:2Wrong Format");
}
if(!swll.matcher(sjsw1).matches()){//如果实际水位不合法
flag=1;flag1=1;
System.out.println("Row:"+(i+1)+",Column:3Wrong Format");
}
if(!kd1.matcher(mbkd1).matches()){//如果目标开度不合法
flag=1;flag1=1;
System.out.println("Row:"+(i+1)+",Column:4Wrong Format");
}
if(!kd1.matcher(sjkd1).matches()){//如果实际开度不合法
flag=1;flag1=1;
System.out.println("Row:"+(i+1)+",Column:5Wrong Format");
}
if(!swll.matcher(liuliang1).matches()){//如果流量不合法
flag=1;flag1=1;
System.out.println("Row:"+(i+1)+",Column:6Wrong Format");
}
if(flag==1){
System.out.println("Data:"+b[i]);
}
else {
if(Double.parseDouble(kd[0])<Double.parseDouble(kd[1])){//目标开度和实际开度相比较
System.out.println("Row:"+(i+1)+" GateOpening Warning");
}
sjsw[i]= Double.parseDouble(hang[2]);//把每行的实际水位的数据放入实际水位的数组里
ll[i]=Double.parseDouble(hang[4]);//把每行的流量的数据放入流量的数组里
h++;
}
}
if(flag1==0){
for(i=0;i<h;i++){//按照行循环
if(max<sjsw[i]){
max=sjsw[i];
}
sum=sum+7200*ll[i];//计算每行总流量并与之前的流量相加
}
System.out.printf("Max Actual Water Level:%.2f\n",max);
System.out.printf("Total Water Flow:%.2f",sum);
}
}
}