题解 | 识别有效的IP地址和掩码并进行分类统计
识别有效的IP地址和掩码并进行分类统计
https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682
import java.util.Scanner;
import java.io.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static int[] ans = new int[7];
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
try {
String line;
while((line = br.readLine()) != null) {
try {
String[] IPandYanma = line.split("\\~");
if(IPandYanma.length != 2) {
ans[5]++;
continue;
}
String[] IPparts = IPandYanma[0].split("\\.");
String[] Yanmaparts = IPandYanma[1].split("\\.");
if(IPparts[0].equals("127")) {
continue;
}
if(!YanmaisIllegal(Yanmaparts)) {
ans[5]++;
continue;
} else {
handleOneIP(IPparts, Yanmaparts);
}
} catch (NumberFormatException e) {
ans[5]++;
}
}
for(int i = 0; i < ans.length; i++) {
bw.write(String.valueOf(ans[i]) + " ");
bw.flush();
}
} catch (IOException e) {
}
}
public static void handleOneIP(String[] IPparts, String[] yanmaParts) {
if(IPparts.length != 4) {
ans[5]++;
return;
}
for(int i = 0; i < IPparts.length; i++) {
String part = IPparts[i];
if(part.isEmpty()) {
ans[5]++;
return;
}
// 检查前导零(长度>1且以0开头,如"01")
if (part.length() > 1 && part.startsWith("0")) {
ans[5]++;
return;
}
if (part.startsWith("+")) {
ans[5]++;
return;
}
//判断各个IP部分是否为空
int Ip = Integer.parseInt(part);
if(Ip < 0 || Ip > 255) {
ans[5]++;
return;
}
}
// 新增:计算IP和掩码的32位二进制
String ipBinary = "";
String yanmaBinary = "";
for (int i = 0; i < 4; i++) {
ipBinary += turnToString(IPparts[i]); // 复用turnToString获取8位二进制
yanmaBinary += turnToString(yanmaParts[i]);
}
// 提取主机位(掩码为0的部分)
String hostBits = "";
for (int i = 0; i < 32; i++) {
if (yanmaBinary.charAt(i) == '0') { // 掩码0对应主机位
hostBits += ipBinary.charAt(i);
}
}
// 若主机位全0(网络地址)或全1(广播地址),判定为非法
if (hostBits.replace("0", "").isEmpty() || hostBits.replace("1", "").isEmpty()) {
}
String IPhead = IPparts[0];
int IP = Integer.parseInt(IPhead);
int IP2 = Integer.parseInt(IPparts[1]);
int IP3 = Integer.parseInt(IPparts[2]);
int target;
if(IP > 0 && IP <= 127) {
ans[0]++;
}
if(IP > 127 && IP <= 191) {
ans[1]++;
}
if(IP > 191 && IP <= 223) {
ans[2]++;
}
if(IP > 223 && IP <= 239) {
ans[3]++;
}
if(IP > 239 && IP <= 255) {
ans[4]++;
}
if(IP == 10 || (IP == 172 && IP2 >=16 && IP2 < 32) || (IP == 192 && IP2 == 168)) {
ans[6]++;
}
}
//判断掩码部分是否合法
public static boolean YanmaisIllegal(String[] input) {
int n = input.length;
if(n != 4) {
return false;
}
StringBuffer sb = new StringBuffer();
//判断是否全为1或全为0
for (int i = 0; i < n; i++) {
if (input[i].isEmpty()) {
return false;
}
if (Integer.parseInt(input[i]) < 0 || Integer.parseInt(input[i]) > 255) {
return false;
}
sb.append(input[i]);
}
if(sb.toString().equals("255255255255") || sb.toString().equals("0000")) {
return false;
}
boolean haveZero = false;
//判断每一部分是否合法
for (int i = 0; i < n; i++) {
int index = 0;
String part = input[i];
if(part.length() > 1 && part.startsWith("0")) {
return false;
}
if(haveZero && !part.equals("0")) {
return false;
}
part = turnToString(part);
char now = part.charAt(0);
for (int j = 1; j < part.length(); j++) {
char last = part.charAt(j);
//好像只需要考虑前一个是0,后一个是1的情况是异常,其余比如00,11,10都是正常的,因为已经排除了极端情况
//事实证明不是这样,在前三个的时候都要标记是否出现了0,如果已经出现了0,后续都不能再出现1
if(now == '0' || last == '0') {
haveZero = true;
if(last == '0') {
continue;
} else {
return false;
}
}
if(last == '1' && haveZero) {
return false;
}
now = last;
}
}
return true;
}
//这个函数将掩码的单个部分转化为八位二进制字符串
public static String turnToString(String part) {
int num = Integer.parseInt(part);
return String.format("%8s", Integer.toBinaryString(num)).replace(' ', '0');
}
}
