题解 | #识别有效的IP地址和掩码并进行分类统计#
识别有效的IP地址和掩码并进行分类统计
http://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682
思路
这道题本质并不复杂,只是细节比较多,需要规划好校验判断的路线
因为判断IP合法过程需要拆分字符串转int数组,考虑到判断后还需要继续分析其int值是否符合范围要求
若是重复split,不可避免出现代码copy的bad smell
因此应该将合法IP的int数组保存下来
但是单纯判断IP合法并不能充分说明这个IP就一定要进入后面的判断过程
比如子网掩码不合法、开头为0或者127
为此定义一个游标cursor,我们认为游标之前的IP是有效的
具体步骤
-
接收数据
-
校验数据
- 校验是否合法IP
- 若是合法IP,则储存下来,但是注意cursor先不要右移
- 若是合法IP,且开头为0或127,则continue,不计入任何计数
- 校验是否合法子网掩码
- 若同时满足合法IP+合法子网掩码,才将cursor右移;否则计入错误IP地址数量
- 校验是否合法IP
-
统计数据
-
遍历cursor之前的所有IP地址,按A~E类分别比对判断
-
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* HJ18 识别有效的IP地址和掩码并进行分类统计
*/
public class Main {
public static void main(String[] args) {
List<String> data = loadDataFromScanner();
// List<String> data = loadTestData();
Analyser analyser = new Analyser(data);
analyser.doAnalyse();
System.out.println(analyser.report());
}
private static List<String> loadDataFromScanner() {
List<String> data = new ArrayList<>();
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
data.add(sc.nextLine());
}
return data;
}
public static class Analyser {
private int a;
private int b;
private int c;
private int d;
private int e;
private int err;
private int self;
private List<String> data;
private List<int[]> ipAddresses;
private int ipAddressCursor;
public Analyser(List<String> data) {
this.data = data;
}
public void doAnalyse() {
init();
for (String s : data) {
String[] arr = s.split("~");
String ip = arr[0];
String mask = arr[1];
boolean legalIp = isLegalIp(ip);
if (legalIp) {
int first = ipAddresses.get(ipAddressCursor)[0];
if (first == 0 || first == 127) {
// 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略
continue;
}
}
boolean legalMask = isLegalMask(mask);
if (legalIp && legalMask) {
++ipAddressCursor;
} else {
// System.out.println(String.format("legalIp: %s, legalMask: %s %s", legalIp, legalMask, s));
++err;
}
}
for (int i = 0; i < ipAddressCursor; i++) {
int[] ipArr = ipAddresses.get(i);
if (isPrivateIp(ipArr)) {
++self;
}
int first = ipArr[0];
if (first <= 126) {
++a;
} else if (first <= 191) {
++b;
} else if (first <= 223) {
++c;
} else if (first <= 239) {
++d;
} else if (first <= 255) {
++e;
}
}
}
private boolean isPrivateIp(int[] ip) {
if (ip[0] == 10) {
return true;
} else if (ip[0] == 172) {
if (ip[1] >= 16 && ip[1] <= 31) {
return true;
}
} else if (ip[0] == 192 && ip[1] == 168) {
return true;
}
return false;
}
private boolean isLegalMask(String mask) {
String[] maskStr = mask.split("\\.");
if (maskStr.length != 4) {
return false;
}
boolean headOne = true;
for (String s : maskStr) {
switch (s) {
case "255":
if (!headOne) {
return false;
}
break;
case "254":
case "252":
case "248":
case "240":
case "224":
case "192":
case "128":
if (!headOne) {
return false;
}
headOne = false;
break;
case "0":
if (headOne) {
headOne = false;
}
break;
default:
return false;
}
}
return !headOne;
}
private boolean isLegalIp(String ip) {
String[] ipStr = ip.split("\\.");
if (ipStr.length != 4) {
return false;
}
int[] ipInt = new int[4];
for (int i = 0; i < 4; i++) {
try {
ipInt[i] = Integer.parseInt(ipStr[i]);
} catch (NumberFormatException ignore) {
return false;
}
}
for (int i : ipInt) {
if (i < 0 || i > 255) {
return false;
}
}
saveIp(ipInt, ipAddressCursor);
return true;
}
private void saveIp(int[] ipInt, int ipAddressCursor) {
if (ipAddressCursor == ipAddresses.size()) {
ipAddresses.add(ipInt);
} else {
ipAddresses.set(ipAddressCursor, ipInt);
}
}
private void init() {
this.a = 0;
this.b = 0;
this.c = 0;
this.d = 0;
this.e = 0;
this.err = 0;
this.self = 0;
this.ipAddresses = new ArrayList<>();
this.ipAddressCursor = 0;
}
public String report() {
return String.format("%s %s %s %s %s %s %s", a, b, c, d, e, err, self);
}
}
private static List<String> loadTestData() {
List<String> data = new ArrayList<>();
data.add("225.240.129.203~255.110.255.255");
data.add("183.181.49.4~255.0.0.0");
data.add("172.177.113.45~255.0.0.0");
data.add("176.134.46.246~255.0.0.0");
data.add("153.63.21.56~255.255.58.255");
data.add("23.135.167.228~255.0.0.0");
data.add("204.58.47.149~255.0.0.0");
data.add("113.33.181.46~255.255.255.0");
data.add("73.245.52.119~255.255.154.0");
data.add("23.214.47.71~255.0.0.0");
data.add("139.124.188.91~255.255.255.100");
data.add("142.94.192.197~255.0.0.0");
data.add("53.173.252.202~255.0.0.0");
data.add("127.201.56.50~255.255.111.255");
data.add("118.251.84.111~255.0.0.0");
data.add("130.27.73.170~255.0.0.0");
data.add("253.237.54.56~255.86.0.0");
data.add("64.189.222.111~255.255.255.139");
data.add("148.77.44.147~255.0.0.0");
data.add("59.213.5.253~255.255.0.0");
data.add("3.52.119.131~255.255.0.0");
data.add("213.208.164.145~255.255.0.0");
data.add("24.22.21.206~255.255.90.255");
data.add("89.43.34.31~255.0.0.0");
data.add("9.64.214.75~255.0.0.0");
data.add("110.156.20.173~255.153.0.0");
data.add("71.183.242.53~255.255.0.0");
data.add("119.152.129.100~255.0.0.0");
data.add("38.187.119.201~255.0.0.0");
data.add("73.81.221.180~255.255.255.255");
data.add("73.198.13.199~255.0.15.0");
data.add("99.42.142.145~255.255.255.0");
data.add("196.121.115.160~255.0.0.0");
data.add("226.30.29.206~255.0.0.0");
data.add("244.248.31.171~255.255.255.255");
data.add("59.116.159.246~255.0.0.0");
data.add("121.124.37.157~255.0.0.226");
data.add("103.42.94.71~255.255.0.0");
data.add("125.88.217.249~255.255.74.255");
data.add("73.44.250.101~255.255.255.0");
return data;
}
}