算法题:判断一个IP是否是合法IP

来源:互联网 发布:ocr表格识别软件 编辑:程序博客网 时间:2024/05/22 08:06

题目:如何判断一个IP是否是合法的IP,如输入:192.168.1.0,输出:合法;输入192.168.1.1222,输出:非法。

解答:先了解IP的格式,它的形式应该为:(1~255).(0~255).(0~255).(0~255)。那么可以有两种方法实现,一种是基于对字符串的处理,另一种是通过强大的正则表达式来判断。下面我将采用熟悉的Java来实现。
方法一:对字符串进行截取、分析等,代码如下:

public static void main(String[] args){    System.out.println("请输入要验证的IP地址:");    Scanner scanner = new Scanner(System.in);    String ipStr = scanner.next();    boolean isIpLegal = isIpLegal(ipStr);    if(isIpLegal) {        System.out.println("合法");    }    else{        System.out.println("非法");    }}public static boolean isIpLegal(String str){    //1.检查ip是否为空    if(str == null){        return false;    }    //2.检查ip长度,最短为:x.x.x.x(7位),最长为:xxx.xxx.xxx.xxx(15位)    if(str.length() < 7 || str.length() > 15){        return false;    }    //3.按"."分割字符串,并判断分割出来的个数,如果不是4个,则是非法IP    String[] arr = str.split("\\.");    if(arr.length != 4){        return false;    }    //4.对分割得到的每个字符串进行单独判断    for(int i = 0; i < arr.length; i++){        //对分割得到的每个字符串的每个字符进行逐一判断,如果不是数字0-9,则判定为非法IP        for(int j = 0; j < arr[i].length(); j++){            if (arr[i].charAt(j) < '0' || arr[i].charAt(j) > '9'){                return false;            }        }    }    //5.对拆分的每一个字符串进行转换成数字,并判断是否在0~255    for(int i = 0; i < arr.length; i++){        int temp = Integer.parseInt(arr[i]);        if(i == 0){            if (temp < 1 || temp > 255){                return false;            }        }        else{            if(temp < 0 || temp > 255){                return false;            }        }    }    //6.最后,如果经过前面验证都没返回到false,返回true    return true;}

乍看这样的判断貌似没什么问题,但是在经过多次测试后发现,会存在三个问题。
(1)如果输入以小数点开头的非法IP,如:.x.x.x.或者.x.x.xx,编译运行后,在int temp = Integer.parseInt(arr[i])一行会有一个NumberFormatExceptin报错;
(2)如果输入以小数点结尾的非法IP,如:x.x.x.x.,最终得到的结果为“合法”;
(3)如果输入带0开头的IP,如:0x.0xx.0x.00x,最终得到的结果为“合法”;

问题(1):仔细分析是由于Java的split()方法截取时出的问题。如果输入为:.x.x.x.或者.x.x.xx的时候,split后得到的数组为arr[4]={“”,”x”, “x”, “x”}和arr[4]={“”,”x”, “x”, “xx”},就会使得后面对字符串转型时的int temp = Integer.parseInt(arr[i])那行报错NumberFormatException;
问题(2):如果输入为:x.x.x.x.,split后得到的数组为arr[4]={“x”,”x”, “x”, “x”},而不会是arr[4]={“x”,”x”, “x”, “x”, “”},根据后面的判断方法,会将此非法IP判定为合法IP。
问题(3):这是因为0xx,在Integer.parseInt()转型时会忽略掉这个0的,因此会通过判定,最后得到认为它是合法的IP。

解决方法:问题(1)(2)需要在截取字符串之前,对输入的字符串的首末字符进行判断,如果是小数点”.”,则判定为非法IP。问题(3)可以在第4步中加入判断,如果分割得到的每个字符串不是一位字符且以”0”开头,则判断为非法IP。完整代码如下:

public static void main(String[] args){    System.out.println("请输入要验证的IP地址:");    Scanner scanner = new Scanner(System.in);    String ipStr = scanner.next();    boolean isIpLegal = isIpLegal(ipStr);    if(isIpLegal) {        System.out.println("合法");    }    else{        System.out.println("非法");    }}public static boolean isIpLegal(String str){    //1.检查ip是否为空    if(str == null){        return false;    }    //2.检查ip长度,最短为:x.x.x.x(7位),最长为:xxx.xxx.xxx.xxx(15位)    if(str.length() < 7 || str.length() > 15){        return false;    }    //3.解决问题(1)(2): 对输入字符串的首末字符判断,如果是"."则是非法IP    if(str.charAt(0) == '.' || str.charAt(str.length()-1) == '.'){        return false;    }    //4.按"."分割字符串,并判断分割出来的个数,如果不是4个,则是非法IP    String[] arr = str.split("\\.");    if(arr.length != 4){        return false;    }    //5.对分割出来的每个字符串进行单独判断    for(int i = 0; i < arr.length; i++){        //解决问题(3): 如果每个字符串不是一位字符,且以'0'开头,则是非法的IP,如:01.002.03.004        if(arr[i].length() > 1 && arr[i].charAt(0) == '0'){            return false;        }        //对每个字符串的每个字符进行逐一判断,如果不是数字0-9,则是非法的IP        for(int j = 0; j < arr[i].length(); j++){            if (arr[i].charAt(j) < '0' || arr[i].charAt(j) > '9'){                return false;            }        }    }    //6.对拆分的每一个字符串进行转换成数字,并判断是否在0~255    for(int i = 0; i < arr.length; i++){        int temp = Integer.parseInt(arr[i]);        if(i == 0){            if (temp < 1 || temp > 255){                return false;            }        }        else{            if(temp < 0 || temp > 255){                return false;            }        }    }    //7.最后,如果经过前面验证都没返回到false,返回true    return true;}

方法二:采用正则表达式,代码如下:

public static void main(String[] args){    System.out.println("请输入要验证的IP地址:");    Scanner scanner = new Scanner(System.in);    String ipStr = scanner.next();    //ip地址范围:(1~255).(0~255).(0~255).(0~255)    String ipRegEx = "^" +            "[1-9]|1\\d{2}|2[0-4]\\d|25[0-5]" +            "(\\.[0-9]|1\\d{2}|2[0-4]\\d|25[0-5]){3}" +            "$";    Pattern pattern = Pattern.compile(ipRegEx);    Matcher matcher = pattern.matcher(ipStr);    boolean isIpLegal = matcher.matches();    if(isIpLegal) {        System.out.println("合法");    }    else{        System.out.println("非法");    }}

从上面两种方法来看,不得不感叹正则表达式的强大。通过正则直接匹配来判断,代码简洁许多。

测试结果:
1.输入:abc,期望结果:非法,实际输出:非法;
2.输入:12345678901234567890,期望结果:非法,实际输出:非法;
3.输入:.1.2.3,期望结果:非法,实际输出:非法;
4.输入:1.2.3.4.,期望结果:非法,实际输出:非法;
5.输入:1.2.3,期望结果:非法,实际输出:非法;
6.输入:1.2.3.4.5,期望结果:非法,实际输出:非法;
7.输入:1.02.003.014,期望结果:非法,实际输出:非法;
8.输入:1a.2.3.4,期望结果:非法,实际输出:非法;
9.输入:1.2a.3.4,期望结果:非法,实际输出:非法;
10.输入:1.2.3a.4,期望结果:非法,实际输出:非法;
11.输入:1.2.3.4a,期望结果:非法,实际输出:非法;
12.输入:0.1.2.3,期望结果:非法,实际输出:非法;
13.输入:-1.1.2.3,期望结果:非法,实际输出:非法;
14.输入:1.-1.2.3,期望结果:非法,实际输出:非法;
15.输入:1.2.-1.3,期望结果:非法,实际输出:非法;
16.输入:1.2.3.-1,期望结果:非法,实际输出:非法;
17.输入:256.1.2.3,期望结果:非法,实际输出:非法;
18.输入:1.256.2.3,期望结果:非法,实际输出:非法;
19.输入:1.2.256.3,期望结果:非法,实际输出:非法;
20.输入:1.2.3.256,期望结果:非法,实际输出:非法;
21.输入:1111.111.111.111,期望结果:非法,实际输出:非法;
22.输入:111.1111.111.111,期望结果:非法,实际输出:非法;
23.输入:111.111.1111.111,期望结果:非法,实际输出:非法;
24.输入:111.111.111.1111,期望结果:非法,实际输出:非法;
25.输入:111.111.111.111,期望结果:合法,实际输出:合法;
26.输入:0.0.0.0,期望结果:非法,实际输出:非法;
27.输入:1.0.0.0,期望结果:合法,实际输出:合法;
28.输入:255.255.255.255,期望结果:合法,实际输出:合法;

原创粉丝点击