话不多说,上代码 1.首先通过字符串切割拿到ip和markCode 2.再对ip进行一步初级过滤,保证ip的合法性,让我下面处理时只用关心ip的分类,最后将ip和markcode放入Map中 3.循环Map,对markCode和ip做处理 3.1优先对markCode做校验(这里耽误了好久。。。)之前认为最简单的地方,实际是最麻烦的。 3.2对ip进行处理,因为前面保证了ip的合法性,这里只需要无脑比较即可(不要喷我),大家有更好的办法请打在公屏上。

总的来说这一题不难,就是逻辑优点多。

import java.util.*;

public class Main {

    static int A;
    static int B;
    static int C;
    static int D;
    static int E;
    static int Fail;
    static int PIP;

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        // 11111111 = 255
        List<String> ipMarks = new ArrayList<>();
        while (s.hasNextLine()){
            String Line = s.nextLine();
            if (Line.equals("")) break;
            ipMarks.add(Line);
        }
        Map<String,String> ipAMarkC = new HashMap<>();
        for (String ipMark : ipMarks) {
            String[] split = ipMark.split("~");
            String ip = split[0];
            String[] num = ip.split("\\.");
            String first = num[0];
     
            if (null != first && !"".equals(first) && !"0".equals(first) && !"127".equals(first)) {
                if (Arrays.asList(num).contains("")){
                    Fail += 1;
                }else {
                    // 保证ip都是合法的
                    ipAMarkC.put(ip, split[1]);
                }
            }
        }
        // System.out.println(ipAMarkC);
        ipAMarkC.forEach(
                (ip, markCode) ->{
                    // 如果掩码校验失败,不校验ip
                    if (markCodeValidate(markCode)){
                        ipHandler(ip);
                    }
                }
        );
        System.out.println(A+" "+B+" "+C+" "+D+" "+E+" "+Fail+" "+PIP);
    }

    // 校验子网掩码这里最麻烦
    private static boolean markCodeValidate(String markCode) {
        String[] codes = markCode.split("\\.");
        String zero = "00000000"; // 补齐8位二进制
        StringBuilder result = new StringBuilder();
        // 这里我用两个count来区分全为0和全为1,大家想想有没有更好的办法
        int zeroCount = 0;
        int twoCount = 0;
        for (String code : codes) {
            if (code.equals("0")) {
                zeroCount++;
            }
            if (code.equals("255")){
                twoCount++;
            }
            String bin = Integer.toBinaryString(Integer.parseInt(code));
            result.append(zero.substring(0,8-bin.length()) + bin); //字符串拼接捏
        }
        if (zeroCount == 4 || twoCount == 4){
            Fail += 1;
            return false;
        }
        // 这里我通过切割判断数组长度,因为子网掩码一定的1和0左右分开的
        String[] split = result.toString().split("[0]");
        if (split.length <= 1){
            return true;
        }
        Fail += 1;
        return false;
    }

    private static void ipHandler(String ip) {
        // 先截取第一个地址处理 abcde类地址
        // 再判断是否是私网ip
        String[] codes = ip.split("\\.");
        Integer firstCode = Integer.valueOf(codes[0]);// 为地址分类
        Integer secondCode = Integer.valueOf(codes[1]);// 为地址分类
        boolean canIsPrivate = false;
        if (firstCode >= 1 && firstCode <= 126){
            A += 1;
            canIsPrivate = true;
        }
        if (firstCode >= 128 && firstCode <= 191){
            B += 1;
            canIsPrivate = true;
        }
        if (firstCode >= 192 && firstCode <= 223){
            C += 1;
            canIsPrivate = true;
        }
        if (firstCode >= 224 && firstCode <= 239) D += 1;
        if (firstCode >= 240 && firstCode <= 255) E += 1;

        if (canIsPrivate){
            // 检查是否为私网地址
            if (firstCode.equals(10)
                    || (firstCode.equals(172) && (secondCode >= 16 && secondCode <= 31))
                    || (firstCode.equals(192) && secondCode.equals(168))){
                PIP += 1;
            }
        }
    }
}