首页 > 试题广场 >

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

[编程题]识别有效的IP地址和掩码并进行分类统计
  • 热度指数:329088 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。

所有的IP地址划分为 A,B,C,D,E五类

A类地址从1.0.0.0到126.255.255.255;

B类地址从128.0.0.0到191.255.255.255;

C类地址从192.0.0.0到223.255.255.255;

D类地址从224.0.0.0239.255.255.255;

E类地址从240.0.0.0255.255.255.255


私网IP范围是:

从10.0.0.0到10.255.255.255

从172.16.0.0到172.31.255.255

从192.168.0.0到192.168.255.255


子网掩码为二进制下前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
(注意二进制下全是1或者全是0均为非法子网掩码)

注意:
1. 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略
2. 私有IP地址和A,B,C,D,E类地址是不冲突的



输入描述:

多行字符串。每行一个IP地址和掩码,用~隔开。

请参考帖子https://www.nowcoder.com/discuss/276处理循环输入的问题。


输出描述:

统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。

示例1

输入

10.70.44.68~255.254.255.0
1.0.0.1~255.0.0.0
192.168.0.2~255.255.255.0
19..0.~255.255.255.0

输出

1 0 1 0 0 2 1

说明

10.70.44.68~255.254.255.0的子网掩码非法,19..0.~255.255.255.0的IP地址非法,所以错误IP地址或错误掩码的计数为2;
1.0.0.1~255.0.0.0是无误的A类地址;
192.168.0.2~255.255.255.0是无误的C类地址且是私有IP;
所以最终的结果为1 0 1 0 0 2 1        
示例2

输入

0.201.56.50~255.255.111.255
127.201.56.50~255.255.111.255

输出

0 0 0 0 0 0 0

说明

类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略         
import java.util.Arrays;
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    // 过滤掉0.* 127.*的地址
    // 优先匹配私网ip
    // 再匹配ABCDE类地址
    // 子网掩码匹配,必须以1起始,并且全0或全1是非法的。
    static int[] result = new int[7];

    static long aLeft = 0x01000000L, aRight = 0x7effffffL;
    static long bLeft = 0x80000000L, bRight = 0xbfffffffL;
    static long cLeft = 0xc0000000L, cRight = 0xdfffffffL;
    static long dLeft = 0xe0000000L, dRight = 0xefffffffL;
    static long eLeft = 0xf0000000L, eRight = 0xffffffffL;

    static long apl = 0x0a000000L, apr = 0x0affffffL;
    static long bpl = 0xac100000L, bpr = 0xac31ffffL;
    static long cpl = 0xc0a80000L, cpr = 0xc0a8ffffL;

    public static long ip2Dec(String ip) {
        String[] ipPoint = ip.split("\\.");
        if (ipPoint.length != 4) return -1;
        long sum = 0;
        for (int i = 24, j = 0; j < 4; ++j, i -= 8) {
            long a = Integer.parseInt(ipPoint[j]);
            sum += a << i;
        }
        return sum;
    }

    public static boolean isIpValid(String ip) {
        long ipDec = ip2Dec(ip);
        return ipDec >= aLeft && ipDec <= eRight;
    }

    public static boolean isMarkValid(String mark) {
        String[] ms = mark.split("\\.");
        if (ms.length != 4 || ms[3].equals("255") || ms[0].equals("0")) return false; 
        String b = "";
        for (String t : ms) {
            b += String.format("%08d", Integer.parseInt(Integer.toBinaryString(Integer.parseInt(t))));
        }
        boolean findZero = false;
        for (int i = 0; i < b.length(); ++ i) {
            if (b.charAt(i) == '0') findZero = true;
            if (findZero && b.charAt(i) == '1') return false;
        }
        return true;
    }

    public static boolean isPrivate(String ip) {
        long a = ip2Dec(ip);
        return (a >= apl && a <= apr) || (a >= bpl && a <= bpr) || (a >= cpl && a <= cpr);
    }

    public static void group(String ip) {
        long a = ip2Dec(ip);
        if (a >= aLeft && a <= aRight) result[0] ++;
        if (a >= bLeft && a <= bRight) result[1] ++;
        if (a >= cLeft && a <= cRight) result[2] ++;
        if (a >= dLeft && a <= dRight) result[3] ++;
        if (a >= eLeft && a <= eRight) result[4] ++;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextLine()) {
            String ipAndMark = in.nextLine();
            String[] arr = ipAndMark.split("~");
            if (arr[0].startsWith("0.") || arr[0].startsWith("127.")) continue;
            if (!isIpValid(arr[0]) || !isMarkValid(arr[1])) {
                result[5] ++;
            }else {
                if (isPrivate(arr[0])) {
                    result[6] ++;
                }
                group(arr[0]);
            }
        }
        for (int r : result) System.out.print(r + " "); 
    }
}

发表于 2024-03-20 12:02:36 回复(0)

这个用例是错的吧,非法掩码怎么数都是14个,就是我红线拉掉的那些,答案是13个,到底多了哪一个?
编辑于 2024-03-16 20:39:01 回复(2)
取巧的解法。不过中途被题目坑了,先感谢下《牛客62664608号》的提示,子网掩码在做进制转换的时候需要补位,不足8位的要在前面补0。例如:1的二进制是:1,要在前面补足七个零补成:00000001。题目真坑;
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int A = 0, B = 0, C = 0, D = 0, E = 0, err = 0, pr = 0;

        while (in.hasNext()) {
            String val = in.nextLine();
            //ip和子网掩码拆分
            String[] vals = val .split("~");
            //ip
            String[] ips = vals[0].split("\\.");
            //子网
            String[] subnets = vals[1].split("\\.");
            //校验无效值
            if (ips[0].equals("0") || ips[0].equals("127")) {
                continue;
            }
            //校验ip和子网掩码是否为空
            if (!checkErr(ips) || !checkErr(subnets) ) {
                err = err + 1;
                continue;
            }

            //类型转换
            //ip
            Integer[] ipis = new Integer[4];
            //子网
            Integer[] subnetis = new Integer[4];
            for (int i = 0 ; i < 4 ; i ++) {
                ipis[i] = Integer.parseInt(ips[i]);
                subnetis[i] = Integer.parseInt(subnets[i]);
                if (ipis[i] > 255 || subnetis[i] > 255) {
                    System.out.println(val);
                }
            }

            //校验错误的子网掩码
            if (!checkSubnet(subnetis)) {
                err = err + 1;
                continue;
            }
            //校验ip类型
            if (ipis[0] >= 1 && ipis[0] <= 126 ) {
                A = A + 1;
            } else if (ipis[0] >= 128 && ipis[0] <= 191 ) {
                B = B + 1;
            } else if (ipis[0] >= 192 && ipis[0] <= 223 ) {
                C = C + 1;
            } else if (ipis[0] >= 224 && ipis[0] <= 239 ) {
                D = D + 1;
            } else if (ipis[0] >= 240 && ipis[0] <= 255 ) {
                E = E + 1;
            }

            //校验是否是私网ip
            if (ipis[0] == 10) {
                pr = pr + 1;
            }
            if (ipis[0].equals(172) && ipis[1] >= 16  && ipis[1] <= 31) {
                pr = pr + 1;
            }
            if (ipis[0].equals(192) && ipis[1].equals(168)) {
                pr = pr + 1;
            }
        }

        System.out.print(A + " " + B + " " + C + " " + D + " " + E + " " + err + " " +
                         pr);
    }
    //校验是否存在空值
    public static boolean checkErr(String[] val) {
        for (String i : val) {
            if (i == null || i.length() < 1) {
                return false;
            }
        }
        return true;
    }

    //校验子网掩码是否合法
    public static boolean checkSubnet(Integer[] vals) {
        if (vals[0].equals(0) || vals[3].equals(255)) {
            return false;
        }
        //true 为1,false为0
        Boolean flag = true;
        for (Integer i : vals) {
            StringBuilder val = new StringBuilder(Integer.toBinaryString(i));
            if (val.length() < 8) {
                for (int z = 0; z < 8 - val.length(); z++) {
                    val.insert(0,0);
                }
            }
            int[] ss = val.chars().toArray();
            for (Integer s : ss) {
                if (flag && s.equals(48)) {
                    flag = false;
                } else if (!flag && s.equals(49)) {
                    return false;
                }
            }
        }
        return true;
    }
}


发表于 2024-03-15 15:54:07 回复(0)
判断子网掩码是否有误的时候,除了题目给的限制要求,其实还暗含着另一个要求,就是子网掩码不能为255.255.255.255(不能全为1
编辑于 2024-03-15 11:38:05 回复(0)
用正则

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static String one2OneTwoSix = "([1-9]|[1-9][0-9]|1[01][0-9]|12[0-6])";
    static String zero2TwoFiveFive =
        "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])";
    static String oneTwoEight2OneNightOne = "(1(2[89]|[3-8][0-9]|9[01]))";
    static String oneNightTwo2TwoTwoThree = "(19[2-9]|2[01][0-9]|22[0-3])";
    static String twoTwoFour2TwoThreeNight = "(22[4-9]|23[0-9])";
    static String twoFourZero2twoFiveFive = "(24[0-9]|25[0-5])";
    static String oneSix2ThreeOne = "(1[6-9]|2[0-9]|3[01])";
    static String A = "(" + one2OneTwoSix + ")(\\." + zero2TwoFiveFive + "){3}";
    static String B = "(" + oneTwoEight2OneNightOne + ")(\\." + zero2TwoFiveFive +
                      "){3}";
    static String C = "(" + oneNightTwo2TwoTwoThree + ")(\\." + zero2TwoFiveFive +
                      "){3}";
    static String D = "(" + twoTwoFour2TwoThreeNight + ")(\\." + zero2TwoFiveFive +
                      "){3}";
    static String E = "(" + twoFourZero2twoFiveFive + ")(\\." + zero2TwoFiveFive +
                      "){3}";
    static String PRIVATE =
        "10(\\." + zero2TwoFiveFive + "){3}|"
        + "172\\.(" + oneSix2ThreeOne + ")(\\." + zero2TwoFiveFive + "){2}|" +
        "192\\.168(\\." + zero2TwoFiveFive + "){2}";
    static String RIGHT = "(" + zero2TwoFiveFive + ")(\\." + zero2TwoFiveFive +
                          "){3}";
    static String one = "0|128|192|224|240|248|252|254";
    static String MASK =
        "(" + one + ")(\\.0){3}|" +
        "255\\.(" + one + ")(\\.0){2}|" +
        "(255\\.){2}(" + one + ")\\.0|" +
        "(255\\.){3}(" + one + ")";

    static Pattern patternMask = Pattern.compile(MASK);
    static String OTHER = "(0|127)(\\.\\d*){3}";
    static Pattern patternOther = Pattern.compile(OTHER);

    static Pattern[] patterns = {Pattern.compile(A), Pattern.compile(B), Pattern.compile(C), Pattern.compile(D), Pattern.compile(E), null, Pattern.compile(PRIVATE)};
    static Pattern patternRight = Pattern.compile(RIGHT);

    public static void main(String[] args) {
        int[] count = new int[7];
        Scanner in = new Scanner(System.in);

        while (in.hasNextLine()) {
            String line = in.nextLine();
            count(line, count);
        }
        for (int i : count) {
            System.out.print(i + " ");
        }
    }
    private static void count(String s, int[] count) {
        String[] split = s.split("~");
        String ip = split[0];
        String mask = split[1];
        Matcher matcherOther = patternOther.matcher(ip);
        if (matcherOther.matches()) {
            return;
        }
        Matcher matcherIp = patternRight.matcher(ip);
        Matcher matcherMask = patternMask.matcher(mask);
        if (!matcherIp.matches() || !matcherMask.matches()) {
            count[5]++;
            return;
        }
        for (int i = 0; i < patterns.length; i++) {
            Pattern pattern = patterns[i];
            if (pattern == null) {
                continue;
            }
            if (pattern.matcher(ip).matches()) {
                count[i]++;
            }
        }

    }

 }


发表于 2024-03-13 17:30:18 回复(0)
0.201.56.50~255.255.111.255
127.201.56.50~255.255.111.255
这个为什么是0 0 0 0 0 0 0 而不是0 0 0 0 0 2 0 
发表于 2024-02-01 10:07:29 回复(1)
将ip地址或掩码转换为整数,然后使用移位操作进行判断
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int aCnt = 0, bCnt = 0, cCnt = 0, dCnt = 0, eCnt = 0, errCnt = 0, privateCnt = 0;
        while (in.hasNextLine()) { // 注意 while 处理多个 case'
            String inputLine = in.nextLine();
            if (inputLine.isEmpty()) break;
            //处理读入的ip地址
            String[] items = inputLine.split("~");
            String ip = items[0];
            String mask = items[1];
            //跳过不属于任何类型的ip
            if (isFmtValid(ip) && (ip.startsWith("0.") || ip.startsWith("127."))) continue;
            if (!isMaskValid(mask) || !isIpValid(ip)) {
                errCnt++;
                continue;
            }
            //判断ip的类型
            Long ipLongVal = getIpLongVal(ip);
            if ((ipLongVal >= getIpLongVal("10.0.0.0") && ipLongVal <= getIpLongVal("10.255.255.255")) ||
                (ipLongVal >= getIpLongVal("172.16.0.0") && ipLongVal <= getIpLongVal("172.31.255.255")) ||
                (ipLongVal >= getIpLongVal("192.168.0.0") && ipLongVal <= getIpLongVal("192.168.255.255"))) {
                privateCnt++;
            }
            if ((ipLongVal >= getIpLongVal("1.0.0.0") && ipLongVal <= getIpLongVal("126.255.255.255"))) {
                aCnt++;
            } else if ((ipLongVal >= getIpLongVal("128.0.0.0") && ipLongVal <= getIpLongVal("191.255.255.255"))) {
                bCnt++;
            } else if ((ipLongVal >= getIpLongVal("192.0.0.0") && ipLongVal <= getIpLongVal("223.255.255.255"))) {
                cCnt++;
            } else if ((ipLongVal >= getIpLongVal("224.0.0.0") && ipLongVal <= getIpLongVal("239.255.255.255"))) {
                dCnt++;
            } else if ((ipLongVal >= getIpLongVal("240.0.0.0") && ipLongVal <= getIpLongVal("255.255.255.255"))) {
                eCnt++;
            }
        }
        System.out.println(aCnt + " " + bCnt + " " + cCnt + " " + dCnt + " " + eCnt + " " + errCnt + " " + privateCnt);
    }
    public static boolean isIpValid(String ip) {
        //格式非法
        return isFmtValid(ip);
    }

    public static Long getIpLongVal(String ip) {
        String[] ipItems = ip.split("\\.");
        Long ipLongVal = 0L;
        for (int i = 0; i < ipItems.length; i++) {
            Long posVal = Long.valueOf(ipItems[i]);
            //计算得到掩码的10进制值
            ipLongVal += (posVal << 8 * (3 - i));
        }
        return ipLongVal;
    }

    //判断ip或掩码格式是否合法
    public static boolean isFmtValid(String ip) {
        String[] ipItems = ip.split("\\.");
        if (ipItems.length != 4) {
            return false;
        } else {
            for (int i = 0; i < ipItems.length; i++) {
                if (!isInteger(ipItems[i]) ||
                        Integer.valueOf(ipItems[i]) > 255 ||
                        Integer.valueOf(ipItems[i]) < 0) {
                    return false;
                }
            }
        }
        return true;
    }

    public static boolean isMaskValid(String mask) {
        //格式非法
        if (!isFmtValid(mask)) return false;
        //格式合法,判断掩码是否合法
        String[] maskItems = mask.split("\\.");
        Long maskVal = getIpLongVal(mask);
        //全0或全1的情况非法
        if (maskVal == 0L || maskVal == ((1L << 32) - 1)) {
            return false;
        }
        maskVal = maskVal << 32;//将计算得到的掩码移到高32位
        if (maskVal > 0) return false;
        //左移32次,如果出现大于0的数,则非法
        for (int i = 0; i < 32; i++) {
            maskVal = maskVal << 1;
            if (maskVal > 0) return false;
        }
        return true;
    }

    public static boolean isInteger(String str) {
        boolean isInt = false;
        try {
            Integer.valueOf(str);
            isInt = true;
        } catch (NumberFormatException e) {
            isInt = false;
        }
        return isInt;
    }
}


发表于 2024-01-29 09:01:36 回复(0)
为什么我这个代码只能通过80%的案例呢。。。。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
  
        testCheckIp();
    }

    public static void testCheckIp() {
        Scanner in = new Scanner(System.in);
        int aNum = 0;
        int bNum = 0;
        int cNum = 0;
        int dNum = 0;
        int eNum = 0;
        int errNum = 0;
        int pNum = 0;
        List<String> errIp = new ArrayList<>();
      /*
        A类地址从1.0.0.0到126.255.255.255;
        B类地址从128.0.0.0到191.255.255.255;
        C类地址从192.0.0.0到223.255.255.255;
        D类地址从224.0.0.0到239.255.255.255;
        E类地址从240.0.0.0到255.255.255.255
         */
        while (in.hasNextLine()) {
            String ipStr = in.nextLine();
            String[] ipArr = ipStr.split("~");

            int firstIp = getIpSeq(ipArr[0], 0);
            if (firstIp == 0 || firstIp == 127) {
                continue;
            }
            if (ipIsInvalid(ipArr[0])) {
                errNum++;
                errIp.add(ipArr[0]);
                continue;
            }

            if (maskIsInvalid(ipArr[1])) {
                errNum++;
                errIp.add(ipArr[1]);
                continue;
            }

            if (firstIp >= 1 && firstIp <= 126) {
                aNum++;
            }
            if (firstIp >= 128 && firstIp <= 191) {
                bNum++;
            }
            if (firstIp >= 192 && firstIp <= 223) {
                cNum++;
            }
            if (firstIp >= 224 && firstIp <= 239) {
                dNum++;
            }
            if (firstIp >= 240 && firstIp <= 255) {
                eNum++;
            }
            int secIp = getIpSeq(ipArr[0], 1);
            if (firstIp == 10 || (firstIp == 172 && secIp >= 16 && secIp <= 31) || (firstIp == 192 && secIp == 168)) {
                pNum++;
            }


        }
        System.out.println(aNum + " " + bNum + " " + cNum + " " + dNum + " " + eNum + " " + errNum + " " + pNum);
    }

    private static boolean ipIsInvalid(String ip) {
        /**
         * 第一部分:匹配3个0~255.(注意后面的一个点)(重复匹配3次)
         * 第二部分:匹配最后的数字0~255
         */
        String regex = "((1[0-9][0-9]\\.)|(2[0-4][0-9]\\.)|(25[0-5]\\.)|([1-9][0-9]\\.)|([0-9]\\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]))";
        return !ip.matches(regex);
    }

    private static boolean maskIsInvalid(String maskIp) {
        String regex = "(255.0.0.0)|(255.255.0.0)|(255.255.255.0)";
        return !maskIp.matches(regex);
    }

    private static int getIpSeq(String ip, int index) {
        String[] ipArr = ip.split("\\.");
        return Integer.parseInt(ipArr[index]);
    }
}


发表于 2023-12-20 21:57:56 回复(0)
第一个数字左移24位 第二个数字左移16位 第三个左移8位 第四个原封不动
乍一看32位好像用int类型刚好  实际上出去符号位只有31位  会溢出  所以得基于long类型来做位运算
子网掩码不合法的情况下  ip输入是0.*或者127.*要优先忽略 这个在题目里并没写出 坑

import java.util.Scanner;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int cntA = 0;
        int cntB = 0;
        int cntC = 0;
        int cntD = 0;
        int cntE = 0;
        int cntError = 0;
        int cntPrivate = 0;
        while (in.hasNext()) { // 注意 while 处理多个 case
            String a = in.next();
            String[] aa = a.split("~");
            if(aa.length != 2) {
                cntError++;
                continue;
            }
            if(aa[0].startsWith("0.") || aa[0].startsWith("127.")) {
                continue;
            }
            long[] ips = splitIp(aa[0]);
            long[] masks = splitIp(aa[1]);
            if(ips == null || masks == null) {
                cntError++;
                continue;
            }
            //校验掩码
            long maskValue = (masks[0] << 24) + (masks[1] << 16) + (masks[2] << 8) + masks[3];
            String maskBinary = Long.toBinaryString(maskValue);
            if(maskBinary.length() != 32 || !maskBinary.matches("^1{1,}0{1,}$")) {
                cntError++;
                continue;
            }
            long ipValue = (ips[0] << 24) + (ips[1] << 16) + (ips[2] << 8) + ips[3];
            if(ipValue >= 1l << 24 && ipValue < 127l << 24) {
                cntA++;
                //System.out.println(aa[1]);
                if(ips[0] == 10) {
                    cntPrivate++;
                }
            }else if(ipValue >= (128l << 24) && ipValue < (192l << 24)) {
                cntB++;
                if(ipValue >= (172l << 24) + (16l << 16) && ipValue < (172l << 24) + (32l << 8)) {
                    cntPrivate++;
                }
            }else if(ipValue >= (192l << 24) && ipValue < (224l << 24)) {
                cntC++;
                if(ips[0] == 192l && ips[1] == 168l) {
                    cntPrivate++;
                }
            }else if(ipValue >= (224l << 24) && ipValue < (240l << 24)) {
                cntD++;
            }else if(ipValue >= (240l << 24) && ipValue < (256l << 24)) {
                cntE++;
            }else{
                //cntError++;
            }
        }
        System.out.println(cntA + " " + cntB + " " + cntC + " " + cntD + " " + cntE + " " + cntError + " " + cntPrivate);
    }
    public static long[] splitIp(String ip) {
        String[] ips = ip.split("\\.");
        long[] res = new long[4];
        if(ips.length != 4) {
            return null;
        }
        for(int i = 0; i < ips.length; i++) {
            try {
                Integer ii = Integer.valueOf(ips[i]);
                if(ii < 0 || ii > 255) {
                    return null;
                }
                if(i == 0 && (ii == 0 || ii == 127)) {
                    return null;
                }
                res[i] = ii;
            }catch(Exception e) {
                return null;
            }
        }
        return res;
    }
}


发表于 2023-12-04 14:44:04 回复(0)
1)这题不需要先判断子网掩码是否合法,得先排除0.*和 127.*,再去判断子网掩码,来满足测试用例中
127.201.56.50~255.255.111.255
这一条。
2)楼上说的“多种不合法输入出现,只算一次不合法”,实测是不对的,重复子网掩码如果 IP 不同,则算作多次计数
发表于 2023-11-27 17:15:06 回复(0)

屎山

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        String s = "";
        int[] res = new int[7];
        Set<Integer> set = new HashSet<>();
        Collections.addAll(set, 0, 128, 192, 224, 240, 248, 252, 254, 255);
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            s = in.nextLine();
            String[] parts = s.split("~");
            if (parts.length != 2) {
                res[5] += 1;
                continue;
            }
            String[] partsIP = parts[0].split("\\.");
            String[] partsMask = parts[1].split("\\.");
            if (partsIP.length != 4 || partsMask.length != 4) {
                res[5] += 1;
                continue;
            }
            int a = 0, b = 0, c = 0, d = 0;
            int am = 0, bm = 0, cm = 0, dm = 0;
            try {
                a = Integer.parseInt(partsIP[0]);
                b = Integer.parseInt(partsIP[1]);
                c = Integer.parseInt(partsIP[2]);
                d = Integer.parseInt(partsIP[3]);
                am = Integer.parseInt(partsMask[0]);
                bm = Integer.parseInt(partsMask[1]);
                cm = Integer.parseInt(partsMask[2]);
                dm = Integer.parseInt(partsMask[3]);
            } catch (NumberFormatException e) {
                res[5] += 1;
                continue;
            }
            if (a == 0 || a == 127) {
                continue;
            }

            if((am==0&&bm==0&&cm==0&&dm==0)||(am==255&&bm==255&&cm==255&&dm==255)){
                res[5]+=1;
                continue;
            }

            if(dm!=0){
                if(am!=255||bm!=255||cm!=255||!set.contains(dm)){
                    res[5]+=1;
                    continue;
                }
            }
            if(cm!=0){
                if(am!=255||bm!=255||!set.contains(cm)){
                    res[5]+=1;
                    continue;
                }
            }
            if(bm!=0){
                if(am!=255||!set.contains(bm)){
                    res[5]+=1;
                    continue;
                }
            }
            if(!set.contains(am)){
                res[5]+=1;
                continue;
            }

            if (a >= 1 && a <= 126 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0 &&
                    d <= 255 ) {
                res[0] += 1;
            } else if (a >= 128 && a <= 191 && b >= 0 && b <= 255 && c >= 0 && c <= 255 &&
                       d >= 0 && d <= 255) {
                res[1] += 1;
            } else if (a >= 192 && a <= 223 && b >= 0 && b <= 255 && c >= 0 && c <= 255 &&
                       d >= 0 && d <= 255) {
                res[2] += 1;
            } else if (a >= 224 && a <= 239 && b >= 0 && b <= 255 && c >= 0 && c <= 255 &&
                       d >= 0 && d <= 255) {
                res[3] += 1;
            } else if (a >= 240 && a <= 255 && b >= 0 && b <= 255 && c >= 0 && c <= 255 &&
                       d >= 0 && d <= 255) {
                res[4] += 1;
            } else {
                res[5] += 1;
            }

            // if(a>=1&&a<=126&&b>=0&&b<=255&&c>=0&&c<=255&&d>=0&&d<=255&&set.contains(am)&&bm==0&&cm==0&&dm==0){
            //     res[0]+=1;
            // }else if(a>=128&&a<=191&&b>=0&&b<=255&&c>=0&&c<=255&&d>=0&&d<=255&&am==255&&set.contains(bm)&&cm==0&&dm==0){
            //     res[1]+=1;
            // }else if(a>=192&&a<=223&&b>=0&&b<=255&&c>=0&&c<=255&&d>=0&&d<=255&&am==255&&bm==255&&set.contains(cm)&&dm==0){
            //     res[2]+=1;
            // }else if(a>=224&&a<=239&&b>=0&&b<=255&&c>=0&&c<=255&&d>=0&&d<=255&&am==255&&bm==255&set.contains(cm)&&dm==0){
            //     res[3]+=1;
            // }else if(a>=240&&a<=255&&b>=0&&b<=255&&c>=0&&c<=255&&d>=0&&d<=255&&am==255&&bm==255&cm==0&&set.contains(dm)){
            //     res[4]+=1;
            // }else{
            //     res[5]+=1;
            // }

            if (a == 10 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0 && d <= 255) {
                res[6] += 1;
            } else if (a == 172 && b >= 16 && b <= 31 && c >= 0 && c <= 255 && d >= 0 &&
                       d <= 255) {
                res[6] += 1;
            } else if (a == 192 && b == 168 && c >= 0 && c <= 255 && d >= 0 && d <= 255) {
                res[6] += 1;
            }
        }

        for (int i = 0; i < 7; i++) {
            System.out.print(res[i] + " ");
        }
    }
}
发表于 2023-11-22 21:18:42 回复(0)
未通过的用例如何查看啊
发表于 2023-11-11 00:05:21 回复(0)
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        ArrayList<String> list = new ArrayList();
        int a = 0;
        int b = 0;
        int c = 0;
        int d = 0;
        int e = 0;
        int errors = 0;
        int si = 0;

        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String[] ss = in.nextLine().split("~");
            String[] one = ss[0].split("\\.");
            String[] two = ss[1].split("\\.");
//             if(ss[0].equals("80.164.71.44")){
// errors++;
//             }
            if (ss.length!=2||one.length != 4 || two.length != 4) {
                errors++;
                continue;
            }
            if (Integer.parseInt(one[0]) == 0 || Integer.parseInt(one[0]) == 127) {
                continue;
            }
            for (String sss : one) {
                if ("".equals(sss)) {
                    errors++;
                    //System.out.println(ss[0]);
                    continue;
                }
            }
            for (String sss : two) {
                if ("".equals(sss)) {
                    errors++;
                    //System.out.println(ss[0]);
                    continue;
                }
            }

            if (Integer.parseInt(one[0]) < 1 || Integer.parseInt(one[0]) > 255 ||
                    Integer.parseInt(two[0]) < 1 || Integer.parseInt(two[0]) > 255) {
                errors++;
                //System.out.println(ss[0]);
                continue;
            }
            String erjinzhi = "";
            for (String er : two) {
                erjinzhi += zhuanhuan(er);
            }
            //判断子网掩码是否非法
            if (erjinzhi.indexOf("0") - erjinzhi.lastIndexOf("1") != 1) {
                errors++;
                continue;
            }

            if (Integer.parseInt(one[0]) >= 1
                    && Integer.parseInt(one[0] ) <= 126) {
                a++;
            }
            if (Integer.parseInt(one[0] ) >= 128
                    && Integer.parseInt(one[0] ) <= 191) {
                b++;
            }
            if (Integer.parseInt(one[0] ) >= 192
                    && Integer.parseInt(one[0] ) <= 223) {
                c++;
            }
            if (Integer.parseInt(one[0]) >= 224
                    && Integer.parseInt(one[0] ) <= 239) {
                d++;
            }
            if (Integer.parseInt(one[0] ) >= 240
                    && Integer.parseInt(one[0]) <= 255) {
                e++;
            }
            if (Integer.parseInt(one[0]) == 10 &&
                    Integer.parseInt(one[1]) >= 0 &&
                    Integer.parseInt(one[2]) >= 0 &&
                    Integer.parseInt(one[3]) >= 0 &&
                    Integer.parseInt(one[1]) <= 255 &&
                    Integer.parseInt(one[2]) <= 255 &&
                    Integer.parseInt(one[3]) <= 255
               ) {
                si++;
            }
            if (Integer.parseInt(one[0]) == 172 &&
                    Integer.parseInt(one[1]) >= 16 &&
                    Integer.parseInt(one[2]) >= 0 &&
                    Integer.parseInt(one[3]) >= 0 &&
                    Integer.parseInt(one[1]) <= 31 &&
                    Integer.parseInt(one[2]) <= 255 &&
                    Integer.parseInt(one[3]) <= 255
               ) {
                si++;
            }
            if (Integer.parseInt(one[0]) == 192 &&
                    Integer.parseInt(one[1]) == 168 &&
                    Integer.parseInt(one[2]) >= 0 &&
                    Integer.parseInt(one[3]) >= 0 &&
                    Integer.parseInt(one[2]) <= 255 &&
                    Integer.parseInt(one[3]) <= 255
               ) {
                si++;
            }



            // if(){

            // }
        }
        System.out.println(a + " " + b + " " + c + " " + d + " " + e + " " + errors +
                           " " + si);
    }
    private static String zhuanhuan(String er) {
        er = Integer.toString(Integer.parseInt(er), 2);
        while (er.length() < 8) {
            er = "0" + er;
        }
        return er;
    }

}
发表于 2023-09-21 11:16:17 回复(0)
子网掩码每一段都是8位2进制数字,
255.16.0.0乍一看是11111111.10000.00000000.00000000,
实际上是 11111111.00010000.00000000.00000000,辣鸡非法掩码🤬,浪费我的时间
发表于 2023-09-14 15:38:37 回复(2)
非常简单
  • 将输入的 IP 和掩码转化为 long 类型以做进一步操作
  • 优先判断是否需要忽略
  • 位运算验证 IP,掩码合法性并计数
  • 直接范围比较A, B, C, D, E 以及私网 IP 的范围并计数
import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        List<String> inputs = new ArrayList<String>();
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            inputs.add(in.nextLine());
        }

        int[] results = statisticIP(inputs);
        for (int v : results) {
            System.out.printf("%d ",v);
        }
    }

    private static int[] statisticIP(List<String> ips) {
        int[] counter = new int[7];

        for (String addr : ips) {
            String[] addrMasks = addr.split("~");
            long ip = parseAddr(addrMasks[0]);
            long mask = parseAddr(addrMasks[1]);

            if (needIgnore(ip)) {
                continue;
            }

            if (!validIp(ip)) {
                counter[5] ++;
                continue;
            }

            if (!validMask(mask)) {
                counter[5] ++;
                continue;
            }

            if (isA(ip)) {
                counter[0] ++;          
            }

            if (isB(ip)) {
                counter[1] ++;
            }

            if (isC(ip)) {
                counter[2] ++;
            }

            if (isD(ip)) {
                counter[3] ++;
            }

            if (isE(ip)) {
                counter[4] ++;
            }

            if (isPrivate(ip)) {
                counter[6] ++;
            }
        }

        return counter;
    }

    static boolean needIgnore(long ip) {
        return (ip >> 24 ) == 127 || (ip >> 24) == 0;
    }

    static boolean isA(long ip) {
        long begin = parseAddr("1.0.0.0");
        long end = parseAddr("126.255.255.255");
        return ip >= begin && ip <= end;
    }

    static boolean isB(long ip) {
        long begin = parseAddr("128.0.0.0");
        long end = parseAddr("191.255.255.255");
        return ip >= begin && ip <= end;
    }

    static boolean isC(long ip) {
        long begin = parseAddr("192.0.0.0");
        long end = parseAddr("223.255.255.255");
        return ip >= begin && ip <= end;
    }

    static boolean isD(long ip) {
        long begin = parseAddr("224.0.0.0");
        long end = parseAddr("239.255.255.255");
        return ip >= begin && ip <= end;

    }
    static boolean isE(long ip) {
        long begin = parseAddr("240.0.0.0");
        long end = parseAddr("255.255.255.255");
        return ip >= begin && ip <= end;
    }

    static boolean isPrivate(long ip) {
        return ip >= parseAddr("10.0.0.0") && ip <= parseAddr("10.255.255.255") ||
        ip >= parseAddr("172.16.0.0") && ip <= parseAddr("172.31.255.255") ||
        ip >= parseAddr("192.168.0.0") && ip <= parseAddr("192.168.255.255") ;
    }

    static boolean validIp(long ip) {
        return ip != -1;
    }

    static boolean validMask(long mask) {
        if (mask == -1) {
            return false;
        }

        if (mask == 0 || (mask & (mask + 1)) == 0) {
            return false;
        }
        
        while ((1L & mask) == 0) {
            mask >>= 1;
        }

        return (mask & (mask + 1)) == 0;
    }

    static long parseAddr(String addr) {
        String[] part = addr.split("\\.");
        if (part.length != 4) {
            return -1;
        }

        long addrVal = 0L;
        for (int i = 0; i < part.length; i++) {
            try {
                int partInt = Integer.parseInt(part[i]);
                addrVal |= partInt;
                if (i < part.length - 1) {
                    addrVal <<= 8;
                }
            } catch (Exception e) {
                return -1;
            }
        }

        return addrVal;
    }
}


发表于 2023-09-09 19:33:25 回复(0)
用例输入
42.53.252.112~255.0.0.0
166.237.7.68~255.0.0.0
136.3.73.64~255.255.0.0
204.29.136.133~255.255.0.245
195.30.208.94~255.255.0.213
154.253.86.183~255.200.255.0
94.164.187.131~255.255.0.0
167.79.164.186~255.0.0.0
194.172.2.64~255.255.0.0
210.212.79.137~255.255.255.42
143.151.137.40~255.255.255.255
184.145.79.157~255.0.0.0
100.214.131.51~255.255.255.255
233.10.182.98~255.0.0.125
99.184.165.228~255.0.0.82
92.20.159.86~255.0.0.0
198.198.174.83~255.0.0.0
17.158.122.89~255.255.75.255
149.253.103.237~255.0.26.0
91.243.182.7~255.0.0.0
36.76.55.4~255.255.255.255
126.54.86.143~255.0.0.0

预期输出
5 4 2 0 0 11 0

我手动算了错误的只有9个,为啥它是11个
发表于 2023-09-01 12:50:59 回复(2)
这个题巨坑的地方在掩码的判断,说是掩码的二进制判断前面是连续的1后面要是连续的0是合法的,如“1.1.1.0”,按照理解前面3个1转换二进制为111后面加个0就是1110,应该是合法的,但坑爹的就是它这个题目的判断1的掩码二进制是00000001,如果二进制不够8位要在前面补0,题目没说这个要补0的操作,我是看了别人的答案对比了很久才发现,如“1.1.1.0”按照题目应该是“00000001000000010000000100000000”,所以“1.1.1.0”是错的掩码,厚礼谢
发表于 2023-08-27 10:21:04 回复(1)

问题信息

难度:
127条回答 90982浏览

热门推荐

通过挑战的用户

查看代码