【算法编程】识别有效的IP地址和掩码并进行分类统计
一.题目描述
请解析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.0~239.255.255.255;
E类地址240.0.0.0~255.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地址和掩码,用~隔开。
输出描述:
统计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
示例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地址,计数时请忽略
二. 解题思路总结:
本题的困难点在于读懂题目以及对子网掩码的判断上,逻辑有点绕;
1.对输入按~分割字符串,字符串数组保存IP地址IPAddr及子网掩码sub,保存IP地址的第一段数字,用于判断范围;
2. 整数A,B,C,D,E,Err,Pri分别用于统计A,B,C ,D,E,错误地址或子网掩码,私有IP地址;
3.A,B,C,D,E段有效地址:首段满足p[0]范围要求 & 其余字段长度大于0 & 子网掩码合法;
在A,B,C有效地址中,顺便处理私有地址;
4. 0和127开头的IP地址不计算;
5.其余均为错误IP地址;
6.子网掩码的有效性判断,结合数组{"254", "252", "248", "240", "224", "192", "128"}比对进行判断。注意
子网掩码为二进制下前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
注意二进制下全是1或者全是0均为非法。
三. Java代码如下:
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,Erro=0,Pri=0;
while (sc.hasNextLine()) {
String str = sc.nextLine();
String[] IP = str.split("\\~"); //按~分割字符串
String IP0 = IP[0];
String IP1 = IP[1];
String[] IPAddr = IP0.split("\\."); //保存IP地址
int[] p = new int[2];
p[0] = Integer.parseInt(IPAddr[0]); //保存IP地址的第一段数字,用于判断范围
String[] sub = IP1.split("\\."); //保存子网掩码
boolean flag = secondNum(sub); //调用函数判断是否合法
if (p[0] >= 1 && p[0] <= 126 && IPAddr[1].length() >= 1 && IPAddr[2].length() >= 1 && IPAddr[3].length() >= 1
&& flag==true) { //A段有效地址
A++;
if ((IPAddr[0].equals("10")))
Pri++; //同时也是私有IP地址
}
else if (p[0] >= 128 && p[0] <= 191 && IPAddr[1].length() >= 1 && IPAddr[2].length() >= 1 && IPAddr[3].length() >= 1
&& flag==true) { //B段有效地址
B++;
if (IPAddr[0].equals("172") && Integer.parseInt(IPAddr[1]) >= 16 &&Integer.parseInt(IPAddr[1]) <= 31)
Pri++; //同时也是有效私有IP地址
} else if (p[0] >= 192 && p[0] <= 223 && IPAddr[1].length() >= 1 && IPAddr[2].length() >= 1 && IPAddr[3].length() >= 1
&& flag==true) { //C段有效地址
C++;
if (IPAddr[0].equals("192") && IPAddr[1].equals("168")) Pri++; //同时也是私有IP地址
}
else if (p[0] >= 224 && p[0] <= 239 && IPAddr[1].length() >= 1 && IPAddr[2].length() >= 1 && IPAddr[3].length() >= 1
&& flag==true) D++; //D段有效地址
else if (p[0] >= 240 && p[0] <= 255 && IPAddr[1].length() >= 1 && IPAddr[2].length() >= 1 && IPAddr[3].length() >= 1
&& flag==true) E++; //E段有效地址
else if (IPAddr[0].equals("0") || IPAddr[0].equals("127")) continue; //0和127开头的IP地址不计算
else Erro++; //其余为错误IP地址
}
System.out.println(A+" "+B+" "+ C+" "+D+" "+ E+" "+ Erro+" "+Pri);
}
//判断掩码是否合法
public static boolean secondNum(String[] arr){
String[] str = {"254", "252", "248", "240", "224", "192", "128"};//二进制以1开头的数组
//判断掩码
if (arr[0].equals("255")) { 逐级判断是否是合法子网掩码
if (arr[1].equals("255")) {
if (arr[2].equals("255")) {
if (Arrays.asList(str).contains(arr[3])) {
return true;
} else if (arr[3].equals("0")) {
return true;
} else {
return false;
}
} else if (Arrays.asList(str).contains(arr[2])) {
if (arr[3].equals("0")) {
return true;
} else {
return false;
}
} else if (arr[2].equals("0") && arr[3].equals("0")) {
return true;
} else {
return false;
}
} else if (Arrays.asList(str).contains(arr[1])) {
if (arr[2].equals("0") && arr[3].equals("0")) {
return true;
} else {
return false;
}
} else if (arr[1].equals("0") && arr[2].equals("0") && arr[3].equals("0")) {
return true;
} else {
return false;
}
} else if (Arrays.asList(str).contains(arr[0])) {
if (arr[1].equals("0") && arr[2].equals("0") && arr[3].equals("0")) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}