题解 | #识别有效的IP地址和掩码并进行分类统计#

识别有效的IP地址和掩码并进行分类统计

https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682

import java.util.Scanner;
import java.util.regex.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // // 注意 hasNext 和 hasNextLine 的区别
        // while (in.hasNextInt()) { // 注意 while 处理多个 case
        //     int a = in.nextInt();
        //     int b = in.nextInt();
        //     System.out.println(a + b);
        // }

        //计算 A,B,C,D,E 错误ip地址/掩码, 私有ip的个数
        //每行 ip~掩码
        //思路:三个函数,isNonIp()(0.*.*.* 和127.*.*.*哪一类都不属于); isValidIp, isValidMark, 判断ABCDE,私网 就仅通过第一段的范围判断即可
        int aCnt = 0;
        int bCnt = 0;
        int cCnt = 0;
        int dCnt = 0;
        int eCnt = 0;
        int errCnt =0;
        int privateCnt =0;

        while(in.hasNext()){
            String str = in.nextLine();
            String[] strs = str.split("~");
            String ip = strs[0];
            String mark = strs[1];
            if(isNonIp(ip) || isNonIp(mark)){
                continue;
            }

            //错误IP地址或错误掩码的计数
            if(!isValidIp(ip) || !isValidMark(mark)){
                errCnt ++;
                continue;
            }

            String label = IpLable(ip);
            switch(label){
                case "A" :
                    aCnt ++;
                    break;

                case "B":
                    bCnt ++;
                    break;
                
                case "C":
                    cCnt ++;
                    break;

                case "D":
                    dCnt ++;
                    break;

                case "E":
                    eCnt ++;
                    break;
            }

            if(isPrivate(ip)){
                privateCnt ++;
            }
        }
        System.out.printf("%d %d %d %d %d %d %d%n", aCnt,bCnt,cCnt,dCnt,eCnt,errCnt, privateCnt);
    }

    /**
        类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略
        这个方法最先调用,否则非法ip会被统计
     */
    public static boolean isNonIp(String ipStr){
        String[] subIps = ipStr.split("\\.");
        if(subIps.length == 4){
            Integer first = Integer.parseInt(subIps[0]);
            return first== 0 || first==127;
        }
        return false;
    }

    /**
        判断是否为有效ip:
        IP的格式,它的形式应该为:(1~255).(0~255).(0~255).(0~255)
     */
    public static boolean isValidIp(String ipStr){
        Pattern pattern = Pattern.compile("[^0-9\\.]");
        if(pattern.matcher(ipStr).find()){   //如果能找到有非数字,非.的字符直接返回
            return false;   
        }
        String[] strs = ipStr.split("\\.");  //注意转义
        if(strs.length != 4){
            return false;
        }
        for(int i =0; i< strs.length; i++){
            if(strs[i] == null || strs[i].length()==0){
                return false;
            }
            Integer sub = Integer.parseInt(strs[i]);
            if(i==0 && (sub == 0 || sub == 127)){
                return false;
            }
            if(sub>=0 && sub<=255){
                continue;
            }else{
                return false;
            }
        }
        return true;
    }

    /**
        判断合法ip后,再判断ip的首段打上ABCDE的标签
     */
    public static String IpLable(String ipStr){
        String[] subIpStrs = ipStr.split("\\.");
        Integer first = Integer.parseInt(subIpStrs[0]);
        if(first >=1 && first<=126){
            return "A";
        }else if(first>=128 && first<=191){
            return "B";
        }else if(first>=192 && first<=223){
            return "C";
        }else if(first>=224 && first<=239){
            return "D";
        }else if(first>=240 && first<=255){
            return "E";
        }else {
            return null;
        }
    }

    /**
        判断完有效ip后,判断是否为私人ip,私人ip和ABCDE不冲突,一个ip可以既是也是
    */
    public static boolean isPrivate(String ipStr){
        String[] subIpStrs = ipStr.split("\\.");
        Integer first = Integer.parseInt(subIpStrs[0]);
        Integer second= Integer.parseInt(subIpStrs[1]);
        if(first==10){
            return true;
        }else if(first == 172 && second>=16 && second<=31){
            return true;
        }else if(first ==192 && second == 168){
            return true;
        }else {
            return false;
        }
    }

    /**
        合法子网掩码为二进制下前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
        (注意二进制下全是1或者全是0均为非法子网掩码)
     */
    public static boolean isValidMark(String ipStr){
        Pattern pattern = Pattern.compile("[^0-9\\.]");
        if(pattern.matcher(ipStr).find()){   //如果能找到有非数字,非.的字符直接返回
            return false;   
        }
        String[] strs = ipStr.split("\\.");  //注意转义
        if(strs.length != 4){
            return false;
        }

        //把四段分别转为二进制str,每一段不够八位前面补零,然后合并起来判断是否含01 即可
        StringBuffer sBuf = new StringBuffer();
        for(String subIpStr: strs){
            Integer subIp = Integer.parseInt(subIpStr);
            String binStr = Integer.toBinaryString(subIp);
            int delta = 8 - binStr.length();
            if(delta>0){  // 不够八位,高位补零
                binStr = String.format("%"+delta+"s","").replace(" ","0") + binStr;
            }
            sBuf.append(binStr);
        }

        String totalBinStr = sBuf.toString();
        if(totalBinStr.contains("01")){
            return false;
        }else if(!totalBinStr.contains("1")){
            return false;
        }else if(!totalBinStr.contains("0")){
            return false;
        }

        return true;
    }
}

全部评论

相关推荐

learYuan:🐕看了都摇头
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务