【劍指Offer】53、表示數值的字符串


  題目描述:

  請實現一個函數用來判斷字符串是否表示數值(包括整數和小數)。例如,字符串"+100", "5e2", "-123"," 3.1416" 和 "-1E-16" 都表示數值。 但是 "12e", "1a3.14", "1.2.3", "+-5" 和 "12e+4.3" 都不是。

  解題思路:

  本題相對還是比較簡單的,重點在於考慮到所有的情況,能夠寫出表示數值的字符串模式,然后就可以根據正則表達式或者字符串匹配的相應方法來做。

  表示數值的字符串遵循共同的模式:A[.[B]][e|EC]或者.B[e|EC]

  以上模式的含義是:A為數值的整數部分,B為跟在小數點之后的小數部分,C為跟在e或者E之后的指數部分。其中,A部分可以沒有,比如小數.123代表0.123。如果一個數沒有整數部分,那么小數部分必須有。

  具體說來,A和C(也就是整數部分和指數部分)都是可能以"+"、"-"開頭或者沒有符號的數字串,B是數字序列,但前面不能有符號。

  我們可以通過順序掃描字符串來判斷是否符合上述模式,首先盡可能多的掃描數字序列(開頭可能有正負號),如果遇到小數點,那么掃描小數部分,遇到e或者E,則開始掃描指數部分。

  除了順序掃描以外,判斷一個字符串是否滿足某個模式,我們很容易想到的一個辦法是使用正則表達式,以下給出這兩種方法代碼實現。

  正則表達式的解法很簡潔,關於正則表達式的語法參考另外一篇博文:正則表達式

  編程實現(Java):

public class Solution {
    /*
        思路:表示數字的字符串遵循模式:A[.[B]][e|EC]或者.B[e|EC]
        A為整數部分,B為小數部分,C為指數部分
        開頭可能有正負號
        兩種方法:逐位判斷、正則表達式
     */
    public boolean isNumeric(char[] str) {
        //方法一:逐位判斷
        if(str==null)
            return false;
        boolean sign=false,decimal=false,hasE=false; //標記符號、小數點、指數符號E是否出現過
        for(int i=0;i<str.length;i++){
            if(str[i]=='e'||str[i]=='E'){ //有E或者e出現
                if(i==str.length-1) //E不能是最后一位,后面必須跟指數
                    return false;
                if(hasE) return false; //E只能出現一次
                hasE=true;
            }else if(str[i]=='.'){
                if(hasE||decimal) //指數不能有.小數點只能出現一次 
                    return false;
                decimal=true;
            }else if(str[i]=='+'||str[i]=='-'){
                //第一次出現,開頭或者e之后
                if(!sign && i!=0 && str[i-1]!='e' && str[i-1]!='E') //不在開頭也不在e之后
                    return false;
                //第二次出現,E之后
                if(sign && str[i-1]!='E' && str[i-1]!='e')
                    return false;
                sign=true;
            }else if(str[i]>'9'||str[i]<'0') //不合法字符
                return false;
        }
        return true;
    }
    
    //方法二:正則表達式
    //+代表出現一次或多次,*代表出現0次或多次,?代表出現0次或者一次
     public boolean isNumeric(char[] str) {
        String string = String.valueOf(str);
        return string.matches("[\\+-]?[0-9]*(\\.[0-9]*)?([eE][\\+-]?[0-9]+)?");
         /*
         為什么是兩個反斜杠
         首先字符串中的\\被編譯器解釋為\ -------》  第一步,編譯器將字符串轉變為“正則表達式”
		然后作為正則表達式,\.又被正則表達式引擎解釋為.   ----------------> 第二步,才開始把第一步的結果當做是正則表達式,開始進行匹配!
		如果在字符串里只寫\.的話,第一步就被直接解釋為.,之后作為正則表達式被解釋時就變成匹配任意字符了
         */
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM