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