描述

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

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

A类地址从1.0.0.0126.255.255.255;

B类地址从128.0.0.0191.255.255.255;

C类地址从192.0.0.0223.255.255.255;

D类地址从224.0.0.0239.255.255.255

E类地址从240.0.0.0255.255.255.255


私网IP范围是:

10.0.0.010.255.255.255

172.16.0.0172.31.255.255

192.168.0.0192.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处理循环输入的问题。

输出描述:

统计ABCDE、错误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地址,计数时请忽略        

解法

此题考察的是字符串的操作。按照如下顺序判断

l  是否需要忽略

l  判断IP是否非法

l  判断子网掩码是否非法

l  判断是否私有IP

l  判断IP的分类

同时需要注意,私有IP地址和A,B,C,D,E类地址是不冲突的,因此这一个IP地址可能被统计为私有地址,也可能是被统计为A,B,C,D,E类地址。

/*

* Copyright (c) waylau.com, 2022. All rights reserved.

 */

package com.waylau.nowcoder.exam.oj.huawei;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.concurrent.atomic.AtomicInteger;

import java.util.stream.Stream;

/**

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

 * 输入描述:请解析IP地址和对应的掩码,进行分类识别。

 * 要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。

 * 输入描述:多行字符串。每行一个IP地址和掩码,用~隔开。

 * 输出描述:统计ABCDE、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。

 *

 * @author <a href="https://waylau.com">Way Lau</a>

 * @since 2022-08-13

 */

public class HJ018IdentifiesValidIpAddressesAndMasks {

    public static void main(String[] args) throws IOException {

              BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

               

              // 输入总行数

              // 以下变量代表ABCDE、错误IP地址或错误掩码、私有IP的个数

              AtomicInteger a = new AtomicInteger(0);

              AtomicInteger b = new AtomicInteger(0);

              AtomicInteger c = new AtomicInteger(0);

              AtomicInteger d = new AtomicInteger(0);

              AtomicInteger e = new AtomicInteger(0);

              AtomicInteger err = new AtomicInteger(0);

              AtomicInteger p = new AtomicInteger(0);

             

               

              // 输入总行数

              Stream<String> lines = br.lines();

               

              lines.forEach(line -> {

                     String[] lineSplit = line.split("~");

                     String ip = lineSplit[0];

                     String mask = lineSplit[1];

                    

                     // 是否需要忽略

                     if (!isIgnoreIp(ip)) {

                            // 判断IP是否非法;

                            if (isIllegalIp(ip) || isIllegalIp(mask)) {

                                   err.incrementAndGet();

                            } else if (isIllegalMask(mask)){ // 判断子网掩码是否非法

                                   err.incrementAndGet();

                            } else {

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

                                   // 一个IP地址可能被统计为私有地址,也可能是被统计为A,B,C,D,E类地址,

                                   // 因此需要分开统计

                                  

                                   // 判断是否私有IP

                                   if (isPrivateIp(ip)) {

                                          p.incrementAndGet();

                                   }

                           

                                   // 判断IP的分类

                                   String[] ipSegments = ip.split("\\.");

                                   int firstSegment = Integer.valueOf(ipSegments[0]);

                                  

                                   if ( 1<=firstSegment && firstSegment<=126) {

                                          a.incrementAndGet();

                                  } else if ( 128<=firstSegment && firstSegment<=191) {

                                          b.incrementAndGet();

                                  } else if ( 192<=firstSegment && firstSegment<=223) {

                                          c.incrementAndGet();

                                  } else if ( 224<=firstSegment && firstSegment<=239) {

                                          d.incrementAndGet();

                                  } else if ( 240<=firstSegment && firstSegment<=255) {

                                          e.incrementAndGet();

                                   } else {

                                          // 忽略

                                   }

                            }

                     }

              });

               

              // 输出

              System.out.println(a + " " + b + " " + c + " " + d

                            + " " + e + " " + err + " " + p);

             

              br.close();

       }

    private static boolean isIgnoreIp(String ip) {

           boolean isIgnoreIp = false;

           String[] ipSegments = ip.split("\\.");

          

           if (ipSegments[0].equals("0") || ipSegments[0].equals("127")) {

                  isIgnoreIp = true;

           }

          

           return isIgnoreIp;

    }

   

    private static boolean isIllegalIp(String ip) {

           boolean isIllegalIp = false;

           String[] ipSegments = ip.split("\\.");

          

           for (int i = 0; i<ipSegments.length; i++) {

                  if(ipSegments[i].isEmpty()) {

                         isIllegalIp = true;

                         break;

                  } else {

                         int ipSegmentNumber = Integer.valueOf(ipSegments[i]);

                         if (ipSegmentNumber<0 || ipSegmentNumber>255) {

                                isIllegalIp = true;

                         }

                  }

           }

 

          

           return isIllegalIp;

    }

   

       private static boolean isIllegalMask(String mask) {

              boolean isIllegalMask = false;

              String[] ipSegments = mask.split("\\.");

              StringBuilder sb = new StringBuilder();

              for (int i = 0; i < ipSegments.length; i++) {

                     String binaryString = Integer.toBinaryString(

                                   Integer.valueOf(ipSegments[i]));

                     // 不足8位前面补齐0

                     while (binaryString.length() < 8) {

                            binaryString = "0".concat(binaryString);

                     }

                    

                     sb.append(binaryString);

              }

              // 32位二进制数中需要同时存在01,且不存在01

              if (sb.toString().contains("1")

                            && sb.toString().contains("0")

                            && !sb.toString().contains("01")) {

                     isIllegalMask = false;

              } else {

                     isIllegalMask = true;

              }

              return isIllegalMask;

       }

   

       private static boolean isPrivateIp(String ip) {

              boolean isPrivateIp = false;

              String[] ipSegments = ip.split("\\.");

              // 私网IP范围是:

              // 10.0.0.010.255.255.255

              // 172.16.0.0172.31.255.255

              // 192.168.0.0192.168.255.255

              if (ipSegments[0].equals("10")

                            || (ipSegments[0].equals("172")

                                          && Integer.valueOf(

                                                        ipSegments[1]) >= 16

                                          && Integer.valueOf(

                                                        ipSegments[1]) <= 31)

                            || (ipSegments[0].equals("192")

                                          && ipSegments[1].equals("168"))) {

                     isPrivateIp = true;

              }

              return isPrivateIp;

       }

   

}

参考引用