题解 | #识别有效的IP地址和掩码并进行分类统计#
非常无语的一道题,要通过所有测试用例,有两点非常重要:
1. 0/127开头的ip地址时,子网掩码不要判断,此例直接continue,不做任何计算...
2. 不是1的情况下,先判断子网掩码,子网掩码错误则ip地址不要再判断了...
以上两点不观察测试用例,根本不知道!
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, W = 0, S = 0; while (sc.hasNextLine()) { String line = sc.nextLine(); String[] mix = line.trim().split("~"); String ip = mix[0], mask = mix[1]; // 非常无语的一点,如果ip开头是0,或者127,后面掩码不做任何判断 String f = ip.split("\\.")[0]; if (f.equals("0") || f.equals("127")) continue; // 掩码判断(非常无语的一点,从测试用例看出,如果子网掩码错误,ip地址不用再判断) if (judgeMask(mask)) { W++; continue; } // IP地址判断(其中,A类地址、B类地址、C类地址包含有私网地址) char classIP = judgeIP(ip); if (classIP == 'F') W++; if (classIP == 'A') { A++; if (judgePrivateIP(ip, classIP)) S++; } if (classIP == 'B') { B++; if (judgePrivateIP(ip, classIP)) S++; } if (classIP == 'C') { C++; if (judgePrivateIP(ip, classIP)) S++; } if (classIP == 'D') D++; if (classIP == 'E') E++; } System.out.println(A + " " + B + " " + C + " " + D + " " + E + " " + W + " " + S + " "); } public static char judgeIP(String ip) { String[] partsIP = ip.split("\\."); if (partsIP[0].equals("0")) return 'G'; // 忽略计数 if (partsIP[0].equals("127")) return 'G'; // 忽略计数 if (partsIP[0].equals("")) return 'F'; // 忽略计数 int p1 = Integer.parseInt(partsIP[0]); if (p1 >= 1 && p1 <= 126) { // 可能 A for (int i = 1; i < 4; i++) { if (partsIP[i].equals("")) return 'F'; if (Integer.parseInt(partsIP[i]) > 255) { return 'F'; } } return 'A'; } if (p1 >= 128 && p1 <= 191) { // 可能 B for (int i = 1; i < 4; i++) { if (partsIP[i].equals("")) return 'F'; if (Integer.parseInt(partsIP[i]) > 255) { return 'F'; } } return 'B'; } if (p1 >= 192 && p1 <= 223) { // 可能 C for (int i = 1; i < 4; i++) { if (partsIP[i].equals("")) return 'F'; if (Integer.parseInt(partsIP[i]) > 255) { return 'F'; } } return 'C'; } if (p1 >= 224 && p1 <= 239) { // 可能 D for (int i = 1; i < 4; i++) { if (partsIP[i].equals("")) return 'F'; if (Integer.parseInt(partsIP[i]) > 255) { return 'F'; } } return 'D'; } if (p1 >= 240 && p1 <= 255) { // 可能 E for (int i = 1; i < 4; i++) { if (partsIP[i].equals("")) return 'F'; if (Integer.parseInt(partsIP[i]) > 255) { return 'F'; } } return 'E'; } return 'F'; // 表示不和法的IP地址 } public static boolean judgePrivateIP(String ip, char classIp) { // ip肯定是合法地址 boolean privateIpFlag = false; // true表示为是私有地址 String[] partsIP = ip.split("\\."); int p1 = Integer.parseInt(partsIP[0]); if (p1 == 10) { privateIpFlag = true; } if (p1 == 172) { int p2 = Integer.parseInt(partsIP[1]); if (p2 >= 16 && p2 <= 31) privateIpFlag = true; } if (p1 == 192) { int p2 = Integer.parseInt(partsIP[1]); if (p2 == 168) privateIpFlag = true; } return privateIpFlag; } public static boolean judgeMask(String mask) { // 错误掩码:全0,全1,0后面还出现了1;全是0或者全是1同样不合法 boolean illegalityMask = false; // 此掩码是否非法 String[] partsM = mask.split("\\."); for (int i = 0; i < 4; i++) { if (partsM[i].equals("")) { illegalityMask = true; break; } int m = Integer.parseInt(partsM[i]); // 0.全0,直接判断非法 if (i == 0 && m == 0) { illegalityMask = true; break; } // 1.大于255,直接判断不合法 if (m > 255) { illegalityMask = true; break; } // 2.此位置为255,结束此位置判断,开始下一个位置判断 if (m == 255) { if (i == 3) { // 4个位置全1,同样不合法 illegalityMask = true; break; } else { continue; } } // 3.此位置小于255,则下一位置必须是0 for (int j = i+1; j < 4; j++) { if (!partsM[j].equals("0")) { illegalityMask = true; break; } } // 4.此位置小于255,且下面的位置均为0 if (m == 0) break; // 前面已经排除了全0,且后序位置都为0,此位置也为0,直接判断合法 if (Integer.toBinaryString(m).length() < 8) { // 转换为二进制,长度小于8,则必然不合法 illegalityMask = true; break; } boolean lowShow1 = false; // 低位出现 1 while (m != 0) { if (m % 2 == 1) lowShow1 = true; if (lowShow1 && m % 2 == 0) { illegalityMask = true; // 低位出现1后高位又出现0 break; } m = m >> 1; } } return illegalityMask; } }