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

非常无语的一道题,要通过所有测试用例,有两点非常重要:
1. 0/127开头的ip地址时,子网掩码不要判断,此例直接continue,不做任何计算...
2. 不是1的情况下,先判断子网掩码,子网掩码错误则ip地址不要再判断了...

以上两点不观察测试用例,根本不知道!

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int A = 0, B = 0, C = 0, D = 0, E = 0, W = 0, S = 0;
        while (sc.hasNextLine()) {
            String line = sc.nextLine();
            String[] mix = line.trim().split("~");
            String ip = mix[0], mask = mix[1];
            // 非常无语的一点,如果ip开头是0,或者127,后面掩码不做任何判断
            String f = ip.split("\\.")[0];
            if (f.equals("0") || f.equals("127")) continue;
            
            // 掩码判断(非常无语的一点,从测试用例看出,如果子网掩码错误,ip地址不用再判断)
            if (judgeMask(mask)) {
                W++;
                continue;
            }
            
            // IP地址判断(其中,A类地址、B类地址、C类地址包含有私网地址)
            char classIP = judgeIP(ip);
            if (classIP == 'F') W++;
            if (classIP == 'A') {
                A++;
                if (judgePrivateIP(ip, classIP)) S++;
            }
            if (classIP == 'B') {
                B++;
                if (judgePrivateIP(ip, classIP)) S++;
            }
            if (classIP == 'C') {
                C++;
                if (judgePrivateIP(ip, classIP)) S++;
            }
            if (classIP == 'D') D++;
            if (classIP == 'E') E++;
        }
        System.out.println(A + " " + B + " " + C + " " + D + " " + E + " " + W + " " + S + " ");
    }

    public static char judgeIP(String ip) {
        String[] partsIP = ip.split("\\.");
        if (partsIP[0].equals("0")) return 'G';  // 忽略计数
        if (partsIP[0].equals("127")) return 'G';  // 忽略计数
        if (partsIP[0].equals("")) return 'F';  // 忽略计数
        int p1 = Integer.parseInt(partsIP[0]);
        if (p1 >= 1 && p1 <= 126) {  // 可能 A
            for (int i = 1; i < 4; i++) {
                if (partsIP[i].equals("")) return 'F';
                if (Integer.parseInt(partsIP[i]) > 255) {
                    return 'F';
                }
            }
            return 'A';
        }
        if (p1 >= 128 && p1 <= 191) {  // 可能 B
            for (int i = 1; i < 4; i++) {
                if (partsIP[i].equals("")) return 'F';
                if (Integer.parseInt(partsIP[i]) > 255) {
                    return 'F';
                }
            }
            return 'B';
        }
        if (p1 >= 192 && p1 <= 223) {  // 可能 C
            for (int i = 1; i < 4; i++) {
                if (partsIP[i].equals("")) return 'F';
                if (Integer.parseInt(partsIP[i]) > 255) {
                    return 'F';
                }
            }
            return 'C';
        }
        if (p1 >= 224 && p1 <= 239) {  // 可能 D
            for (int i = 1; i < 4; i++) {
                if (partsIP[i].equals("")) return 'F';
                if (Integer.parseInt(partsIP[i]) > 255) {
                    return 'F';
                }
            }
            return 'D';
        }
        if (p1 >= 240 && p1 <= 255) {  // 可能 E
            for (int i = 1; i < 4; i++) {
                if (partsIP[i].equals("")) return 'F';
                if (Integer.parseInt(partsIP[i]) > 255) {
                    return 'F';
                }
            }
            return 'E';
        }
        return 'F';  // 表示不和法的IP地址
    }

    public static boolean judgePrivateIP(String ip, char classIp) {
        // ip肯定是合法地址
        boolean privateIpFlag = false;  // true表示为是私有地址
        String[] partsIP = ip.split("\\.");
        int p1 = Integer.parseInt(partsIP[0]);
        if (p1 == 10) {
            privateIpFlag = true;
        }
        if (p1 == 172) {
            int p2 = Integer.parseInt(partsIP[1]);
            if (p2 >= 16 && p2 <= 31) privateIpFlag = true;
        }
        if (p1 == 192) {
            int p2 = Integer.parseInt(partsIP[1]);
            if (p2 == 168) privateIpFlag = true;
        }
        return privateIpFlag;
    }

    public static boolean judgeMask(String mask) {
        // 错误掩码:全0,全1,0后面还出现了1;全是0或者全是1同样不合法
        boolean illegalityMask = false;  // 此掩码是否非法
        String[] partsM = mask.split("\\.");
        for (int i = 0; i < 4; i++) {
            if (partsM[i].equals("")) {
                illegalityMask = true;
                break;
            }
            int m = Integer.parseInt(partsM[i]);
            // 0.全0,直接判断非法
            if (i == 0 && m == 0) {
                illegalityMask = true;
                break;
            }
            // 1.大于255,直接判断不合法
            if (m > 255) {
                illegalityMask = true;
                break;
            }
            // 2.此位置为255,结束此位置判断,开始下一个位置判断
            if (m == 255) {
                if (i == 3) {  // 4个位置全1,同样不合法
                    illegalityMask = true;
                    break;
                } else {
                    continue;
                }
            }
            // 3.此位置小于255,则下一位置必须是0
            for (int j = i+1; j < 4; j++) {
                if (!partsM[j].equals("0")) {
                    illegalityMask = true;
                    break;
                }
            }
            // 4.此位置小于255,且下面的位置均为0
            if (m == 0) break;  // 前面已经排除了全0,且后序位置都为0,此位置也为0,直接判断合法
            if (Integer.toBinaryString(m).length() < 8) {  // 转换为二进制,长度小于8,则必然不合法
                illegalityMask = true;
                break;
            }
            boolean lowShow1 = false;  // 低位出现 1
            while (m != 0) {
                if (m % 2 == 1) lowShow1 = true;
                if (lowShow1 && m % 2 == 0) {
                    illegalityMask = true;  // 低位出现1后高位又出现0
                    break;
                }
                m = m >> 1;
            }
        }
        return illegalityMask;
    }
}


全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务