7-1 水文数据校验及处理


  

 此题咋看之下很复杂,似乎比求导还要繁琐,其实不然,此题只需要在分割字符串后对单独项进行检验,之后根据检验结果作出相对应的输出即可。

   首先贴一张主函数图

while(!(s=in.nextLine()).equals("exit")){
            //记录行数
            cnt++;
            if(s.length()==0) continue;
            //预处理字符串,返回分割后字符串数组
            String [] arrayString=Preprocessing(s);
            //检验整体合法
            if(!checkArray(arrayString)){
                System.out.println("Wrong Format");
                System.out.println("Data:"+s);
                continue;
            }

            //如果分隔合法,则对各数据进行分别进行合法检验,如果返回值为真进行,加入总流量中
            if(checkArrayAll(arrayString,cnt,s)) {
                sum += Double.valueOf(arrayString[4]) * 60 * 60 * 2;
                mmax= Math.max(mmax,Double.valueOf(arrayString[2]));
            }
        }
             if(mark==0){
                   System.out.printf("Max Actual Water Level:%.2f\n",mmax);
                   System.out.printf("Total Water Flow:%.2f\n",sum);
               }

 

1.对字符串进行分割处理

   1)对于输入的字符串我们可以这样处理,首先检验字符串非空,通过判断字符串长度是否为0,可以选择跳出此处循环,或继续执行下一行代码

   if(s.length()==0) continue

    2)对于非空数据,我们再对其进行整体判断是否能被|恰好分割为5部分,通过使用自定义的boolean函数来判断是否数据合法,根据题目要求,每一条这样的数据我们需要输出"Wrong Format"及该条数据。

   //预处理字符串,返回分割后字符串数组
    String [] arrayString=Preprocessing(s);
            //检验整体合法
    if(!checkArray(arrayString)){
         System.out.println("Wrong Format");
         System.out.println("Data:"+s);
         continue;
      }

 //去除两端空格,同时根据|来切开字符串,检验该数据是否是由|分开的5部分
    public static String []Preprocessing(String s){
        return s.trim().split("\\|");
    }

    //对返回字符串数组进行检验
    public static boolean checkArray(String[] s){
        if(s.length!=5) return false;
        return true;
    }

2.对字符串各部分进行合法判断

  对于分割后产生的5部分字符串,由于题目要求不仅要判断合法性,还需要我们指出错误行数,和列数,我们需要对其进行分开检验。

  大体思路为先使用正则表达式对其进行合法检验,只要检测到该数据不合法便可以直接输出,所在行数我们可以使用一个计数器变量来记录这是第几条数据,将其作为参数传入自定义的检验函数中,所在列数我们可以根据该字符串再切割后的字符串数组的索引+1得到。

  好了,有了这样的大体思路,我们就可以愉快的写出各个数据的正则啦。具体如下:

 //                     /所有年份             /1-12都有1-28 /          1,3,5,7,8,10,12都有1-31天                  /除2月外 都有29-30天
String regex1="(?:((?:([1-9]([0-9]{0,3}))/((?:(([1-9]|(1[0-2]))/(?:([1-9]|([1-2][0-8])|19))))|(?:(([13578])|([1][02])(/31)))|(?:(([13-9]|1[02])/(29|30)))))(?:(?:( [02468]| 1[02468]| 2[02]|):00))))";
//闰年正则,可写可不写,某个坑人的老师骗我写闰年准则,美好的青春就这样在掉头发的时光中度过了
//1或2位闰年                                /3,4位闰年                                                     //400年一润,百年不润
 String regex2="(?:((?:([48]|[2468][048]|[13579][26]))|((?:(([1-9]([0-9]?))?:(0[48]|[2468][048]|[13579][26])))|(?:([48]|[2468][048]|[13579][26])00))/2/29)(?:(?:( [02468]| 1[02468]| 2[02]|):00)))";
 String regexend=regex1+"|"+regex2;
//水位数据正则 目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
  String water ="(?:(?:(([1-9]([0-9]{0,2})))(?:((.[0-9]{1,3})?))))";
//开度正则
  String hot="(?:(([1-9])(?:(.[0-9]{2}))))";
//流量正则同水位

  对于以上检验,

  1)在函数设立局部变量,用来统计是否有不合法的数据,只要有不合法数据,该条数据整体就需要打印

  2)可以在类中设立全局变量,用来统计是否有不合法的数据,只要存在不合法数据,便修改标记,用来作为最后是否需要打印最大实际水位和总流量

  if(mark==0){
                   System.out.printf("Max Actual Water Level:%.2f\n",mmax);
                   System.out.printf("Total Water Flow:%.2f\n",sum);
               }

 

import java.util.Scanner;
public class Main {
    //记录是否全为合法数据
    static int mark=0;
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        String s=null;
        int cnt=0;
        //记录总流量
        double sum=0;
        //记录最大实际水位
        double mmax=0;
        while(!(s=in.nextLine()).equals("exit")){
            //记录行数
            cnt++;
            if(s.length()==0) continue;
          
            //预处理字符串,返回分割后字符串数组
            String [] arrayString=Preprocessing(s);
            //检验整体合法
            if(!checkArray(arrayString)){
                System.out.println("Wrong Format");
                System.out.println("Data:"+s);
                continue;
            }

            //如果分隔合法,则对各数据进行分别进行合法检验,如果返回值为真进行,加入总流量中
            if(checkArrayAll(arrayString,cnt,s)) {
                sum += Double.valueOf(arrayString[4]) * 60 * 60 * 2;
                mmax= Math.max(mmax,Double.valueOf(arrayString[2]));
            }
        }
             if(mark==0){
                   System.out.printf("Max Actual Water Level:%.2f\n",mmax);
                   System.out.printf("Total Water Flow:%.2f\n",sum);
               }

    }
    //去除两端空格,同时根据|来切开字符串,检验该数据是否是由|分开的5部分
    public static String []Preprocessing(String s){
        return s.trim().split("\\|");
    }
    //对返回字符串数组进行检验
    public static boolean checkArray(String[] s){
        if(s.length!=5) return false;
        return true;
    }
    public static boolean checkArrayAll(String[] s,int rows,String data){
        boolean flag=true;
        for(int i=0;i<=4;i++)
            s[i]=s[i].trim();   //去除多余空格
        String test=s[0];
        //检查日期时间合法
        /*
        格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],
        “月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),
        “时”为一位数时之前不加“0”,
        “分”始终保持两位,“秒”始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
         */

        //时间正则
        String time="(?:(?:( [1-9]| 1[0-9]| 2[0-3]| 00):00))";
        //日期正则,空格也会有影响,注意空格
        //                         /所有年份                                /1-12都有1-28                            /1,3,5,7,8,10,12都有1-31天                         /除2月外 都有29-30天
        String regex1="(?:((?:([1-9]([0-9]{0,3}))/((?:(([1-9]|(1[0-2]))/(?:([1-9]|([1-2][0-8])|19))))|(?:(([13578])|([1][02])(/31)))|(?:(([13-9]|1[02])/(29|30)))))(?:(?:( [02468]| 1[02468]| 2[02]|):00))))";
        //1或2位闰年                                /3,4位闰年                                                     //400年一润,百年不润
        String regex2="(?:((?:([48]|[2468][048]|[13579][26]))|((?:(([1-9]([0-9]?))?:(0[48]|[2468][048]|[13579][26])))|(?:([48]|[2468][048]|[13579][26])00))/2/29)(?:(?:( [02468]| 1[02468]| 2[02]|):00)))";
        String regexend=regex1+"|"+regex2;

        if(!test.matches(regexend)) {System.out.printf("Row:%d,Column:%dWrong Format\n",rows,1);flag=false;}

        //检查水位数据合法
        test=s[1];
        //水位数据正则 目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
        String water ="(?:(?:(([1-9]([0-9]{0,2})))(?:((.[0-9]{1,3})?))))";
        if(!test.matches(water)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,2);flag=false;}
        test=s[2];
        if(!test.matches(water)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,3);flag=false;}

        //检查开度
        test=s[3];
        int id=test.indexOf("/");

        String test1=test.substring(0,id);  //目标开度
        String test2=test.substring(id+1,test.length());//实际开度
        String hot="(?:(([1-9])(?:(.[0-9]{2}))))";

        if(!test1.matches(hot)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,4);flag=false;}
        if(!test2.matches(hot)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,5);flag=false;}

        //检查流量合法
        test=s[4];
        if(!test.matches(water)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,6);flag=false;}

        //如果开度输入合法但大小不合法
        double target=Double.valueOf(test1);
        double actual=Double.valueOf(test2);
        if(flag)
            if (actual > target) System.out.printf("Row:%d GateOpening Warning\n",rows);

        //如果存在不合法的数据,打印一次该数据未处理前的原数据
        if(flag==false) System.out.println("Data:"+data);
        if(flag==false) mark=1;
        return flag;
    }

}
class waterDate{
    String time;
    String targerLevel;//目标水位
    String actualLevel;//实际水位
    String targerOpenness;//目标开度
    String actualOpenness;//实际开度


}
/*
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
 */

 

 

 

  目前只是提及了大致思路和正则,一些类似去掉两边空格,和实际开度过高打印并未提及。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM