题目主要信息

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

2、IP分类

  • 所有的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.0~239.255.255.255;
  • E类地址240.0.0.0~255.255.255.255

3、私网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

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

注意二进制下全是1或者全是0均为非法

5、类似于【0...】和【127...】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略

6、 私有IP地址和A,B,C,D,E类地址是不冲突的

方法一:遍历检查

具体做法

直接遍历每一行的IP和子网掩码

  1. 根据~将字符串分割,分成ip和mask,分割完后严重ip是否合法,不合法直接跳过,不需要比较子网掩码
  2. 分别验证ip和子网掩码是否合法
  • 在验证ip的过程中,判断是否符合ip地址的要求,不符合就返回false
  • 验证子网掩码过程中,判断是否符合子网掩码的要求,不符合返回false
  • (11111110(254)、11111100(252)、11111000(248)、11110000(240)、1110000(224)、11000000(191)、10000000(128),全0和全1都不合法)
  • 如果ip和子网掩码均合法,需要判断属于哪一类的ip地址

最后输出结果即可

alt

Java代码

代码中都详细注释

import java.util.*;
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int[] count = new int[7];
        String in;
        while ((in = bf.readLine()) != null) {
            //以~分隔
            String[] split=in.split("~");
            String ip=split[0];//获取IP地址
            String mask=split[1];//获取子网掩码

            String[] ips = ip.split("\\.");
            int num1 = 0;
            int num2 = 0;
            try{
                num1=Integer.parseInt(ips[0]);
                num2=Integer.parseInt(ips[1]);
                Integer.parseInt(ips[2]);
                Integer.parseInt(ips[3]);
            }catch(NumberFormatException e){
                count[5]++;
                continue;
            }


            //1、先判IP地址是否合法
            boolean isIP=isIP(ip);
            boolean isMask=isMask(mask);
            //如果IP和子网掩码都合法 就判断是哪种类型的IP地址
            if(isIP && isMask){
                count = countIP(ip,count);
            }else if((isIP == false || isMask == false) &&num1 != 127 && num1 != 0) {
                count[5]++;
            }
        }
        for(int i=0;i<6;i++)
            System.out.print(count[i]+" ");
        System.out.print(count[6]);
    }

    //判断IP是否合法
    public static boolean isIP(String IP){
        //1. 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时可以忽略
        String[] IParr = IP.split("\\.");
        Boolean isTrue = true;
        for (int i = 0; i < IParr.length; i++) {
            if (IParr[i].length() <= 0 || IParr[i] == "") {//非法判断
                isTrue = false;
            }
        }
        return isTrue;
    }
    //判断子网掩码是否合法
    public static boolean isMask(String mask){
        String[] maskarr = mask.split("\\.");
        boolean result = false;
        //0000 0000~ 1111 1110 八位
        //子网掩码为二进制下前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
        // 注意二进制下全是1或者全是0均为非法
        int[] maskRange = {254, 252, 248, 240, 224, 192, 128, 0};
        List<Integer> list = new ArrayList();
        for(int i:maskRange)
            list.add(i);
        //255.255.255.
        if ("255".equals(maskarr[0])&&"255".equals(maskarr[1])&&"255".equals(maskarr[2])) {
            if (list.contains(Integer.parseInt(maskarr[3]))) {
                result=true;
            }
        }
        //255.255.
        else if("255".equals(maskarr[0])&&"255".equals(maskarr[1])){
            if(list.contains(Integer.parseInt(maskarr[2]))&&"0".equals(maskarr[3])){
                result=true;
            }
        }
        //255.
        else if("255".equals(maskarr[0])){
            if(list.contains(Integer.parseInt(maskarr[1]))&&"0".equals(maskarr[2])&&"0".equals(maskarr[3])){
                result=true;
            }
        }else if(list.contains(Integer.parseInt(maskarr[0]))){
            if("0".equals(maskarr[1])&&"0".equals(maskarr[2])&&"0".equals(maskarr[3])){
                result=true;
            }
        }
        return result;
    }//method end

    //私有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*/
    public static boolean isPrivateIP(String IP){
        String[] split = IP.split("\\.");
        //根据范围即可
        if(Integer.parseInt(split[0])==10) return true;
        else if(Integer.parseInt(split[0])==172&&(Integer.parseInt(split[1])>15&&Integer.parseInt(split[1])<32)){
            return true;
        }else if(Integer.parseInt(split[0])==192&&Integer.parseInt(split[1])==168){
            return true;
        }else{
            return false;
        }
    }
    //各类ip计数
    public static int[] countIP(String IP,int[] count){
        String[] split = IP.split("\\.");
        int first=Integer.parseInt(split[0]);
        //如果是私有ip
        if(isPrivateIP(IP)) count[6]++;

        //判断其他地址范围
/*        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*/
        if (first >= 1 && first <= 126)
            count[0]++;
        else if (first >= 128 && first <= 191)
            count[1]++;
        else if (first >= 192 && first <= 223)
            count[2]++;
        else if (first >= 224 && first <= 239)
            count[3]++;
        else if (first >= 240 && first <= 255)
            count[4]++;
        return count;
    }

}

复杂度分析

  • 时间复杂度:O(n)O(n)nn为字符串长度,遍历整个字符串,后续的循环都是常数时间
  • 空间复杂度:O(n)O(n),存储ip和mask都需要额外空间,空间复杂度为O(n)O(n)

方法二:正则表达式

具体做法

根据要求写出正则表达式即可,这里借助Python语言,Python在爬虫领域对正则的使用是比较频繁的。

Python 3代码

import re
#各类的地址的正则表达式
Error_pattern = re.compile(r'1+0+')
A_pattern = re.compile(r'((12[0-6]|1[0-1]\d|[1-9]\d|[1-9])\.)((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){2}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)')
B_pattern = re.compile(r'(12[8-9]|1[3-8]\d|19[0-1])\.((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){2}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)')
C_pattern = re.compile(r'(19[2-9]|2[0-1]\d|22[0-3])\.((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){2}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)')
D_pattern = re.compile(r'(22[4-9]|23\d)\.((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){2}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)')
E_pattern = re.compile(r'(24\d|25[0-5])\.((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){2}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)')
self_pattern = re.compile(r'((10\.((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){2}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d))|(172\.(1[6-9]|2\d|3[0-1])\.(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d))|(192\.168\.(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)))')
Escape = re.compile(r'((0|127)\.((1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.){2}(1\d\d|2[0-4]\d|25[0-5]|[1-9]\d|\d))')

def ismask(line):
    if line == '255.255.255.255' or line == '0.0.0.0': #全0全1均不合法 
        return 0
    judge = line.split('.') 
    res = ''
    for j in judge:
        res += '{:0>8b}'.format(int(j))
    res = re.fullmatch(Error_pattern, res)
    if res == None:
        return 0
    else:
        return 1

def judge(pattern, line): 
    if re.fullmatch(pattern, line) != None:
        return 1
    else:
        return 0

arr = [0]*7
while True:
    try:
        line = input().split('~') #根据~分割ip地址和掩码
        if line[0][0:4] == "127." or line[0][0:2] == "0.":  #优先判断127或者0开头的
            continue
        if ismask(line[1]): #先判断掩码是否正确
            #正则比较各个IP地址
            if judge(self_pattern, line[0]): #私有与其他的不冲突,优先单独匹配
                arr[6] += 1
            if judge(A_pattern, line[0]):
                arr[0] += 1
            elif judge(B_pattern, line[0]): 
                arr[1] += 1
            elif judge(C_pattern, line[0]):
                arr[2] += 1
            elif judge(D_pattern, line[0]):
                arr[3] += 1
            elif judge(E_pattern, line[0]):
                arr[4] += 1
            elif judge(Escape, line[0]):
                continue
            else:
                arr[5] += 1 #IP地址错误
        else: #掩码错误
            arr[5] += 1
    except:
        print(' '.join([str(i) for i in arr])) #输出
        break

复杂度分析

  • 时间复杂度:O(n)O(n),主要是正则匹配的复杂度
  • 空间复杂度:O(n)O(n),存储ip和mask都需要额外空间,空间复杂度为O(n)O(n)