題目描述
完成一個名稱為「myRegex」的類別,這個類別包含了一個字串樣本。您必須寫出一個正規表示式提供給這個樣本使用,使它可以被用來驗證IP位址。
IP位址的定義如下:
一些合法的IP位址如下:
121.234.12.12
23.45.12.56
一些不合法的IP位址如下:
666.666.23.23
.213.123.23.32
23.45.22.32.
I.Am.not.an.ip
在這個題目中,您將會得到多個由ASCII字元組成的字串,您必須寫出正規表示式,來找出這些字串中哪些是合法的IP位址。注意myRegex類別不可以使用public修飾。
原題網址
範例輸入
121.234.12.12
23.45.12.56
00.12.123.123123.123
122.23
Hello.IP
範例輸出
true
true
false
false
false
解題概念
不超過3位數,範圍0到255且可以由0開頭的整數字串的正規表示式該如何撰寫呢?
首先考慮到「25X」的情況,X的範圍只能在0到5(包含0和5),因此可以寫出以下正規表示式(數值範圍為250到255):
"25[0-5]"
再來考慮到「2XY」但不是「25X」的情況,X的範圍只能在0到4(包含0和4),Y的範圍可以是0到9(包含0和9),因此可以寫出以下正規表示式(數值範圍為200到249):
"2[0-4][0-9]"
再來考慮到「1XY」的情況,X和Y的範圍都可以是0到9(包含0和9),因此可以寫出以下正規表示式(數值範圍為100到199):
"1[0-9][0-9]"
再來考慮到「0XY」的情況,X和Y的範圍都可以是0到9(包含0和9),開頭的0和X可以被省略掉,因此可以寫出以下正規表示式(數值範圍為000到099、00到99、0到9):
"[0]?[0-9]?[0-9]"
用OR運算合併以上式子,不超過3位數,範圍0到255且可以由0開頭的整數字串的正規表示式可以撰寫如下:
"25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9]"
IP位址的格式中,0到255的整數有4個,每個整數中間都使用「.」來分隔,可以很直覺的寫出以下正規表示式:
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])"
化簡重複的部份後,得到:
"((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])"
若I為「(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])」,繼續化簡,得到:
"(I.){3}I"
由於IP不能是「A0.0.0.0B」等等的字串,因此還需要加上字串的起頭與結尾判斷,所以最後的正規表示式為:
"\\A(I.){3}I\\z"
要將I替換回「(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])」。
參考答案
import java.util.Scanner;
public class Solution {
public static void main(final String[] args) {
final Scanner in = new Scanner(System.in);
while (in.hasNext()) {
final String IP = in.next();
System.out.println(IP.matches(new myRegex().pattern));
}
}
}
class myRegex{
private static final String REGEX_0_TO_255 = "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0]?[0-9]?[0-9])";
public final String pattern = String.format("\\A(%s\\.){3}%s\\z", REGEX_0_TO_255, REGEX_0_TO_255);
}