题解 | #识别有效的IP地址和掩码并进行分类统计#
识别有效的IP地址和掩码并进行分类统计
https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682
题解参考了https://www.nowcoder.com/discuss/353149736708415488?sourceSSR=users的思路,但进行了一些自己的改进,也列出了一些说明,可以看做对以上题解的补充,帮助小白理解。
完整思路:
1.【0.*.*.*】和【127.*.*.*】的IP地址应当忽略,因此应该首先判断IP首位是否为0或127;
2.判断IP是否符合基本格式,即四位数字,由'.'隔开,每位数字在0-255之间;定义函数进行判断:
def IP_check(IP): #对IP的基本检查:如果长度不为4或者某位数字不在0-255之间,说明格式不对 if len(IP)!=4: return False for i in IP: if not i.isnumeric(): #不是数字的情况 return False i=int(i) if i<0 or i>255: return False return True
3.判断掩码是否合法;
这一步应该是整个流程中最容易出错的,反正我前几次提交都是因为非法掩码分类出错而失败的。
个人认为需要注意的点:32转成二进制为100000,255,255,255,32如果不考虑位数只拼接二进制字符串,是满足连续的1后面全是0的要求的,然而题目指明255.255.255.32是非法掩码,这说明32的二进制格式应该补齐位数到8位(也就是255转二进制后的位数),左边不足的补0,这样造成0后面有1的情况,导致冲突。因此我们遍历每位数字,将其转换为二进制后补齐位数到8再拼接字符串。拼接完成后,最后一位“1”应在第一位“0”前,如果找不到1或者0,说明掩码是非法的;
def mask_check(mask): #对掩码的基本检查:全为1/全为0/0后有1均为非法 if not IP_check(mask):#掩码也要满足长度为4,每位在0-255之间的要求 return False mask_string="" for m in mask: ms=bin(int(m))[2:] mask_string+=ms.zfill(8) #.zfill:返回指定长度的字符串,原字符串右对齐,前面填充0 #找最后一个1和第一个0的位置;如果相差不是1则0后必有1,如果只有0或只有1,必然不可能相等(返回-1) return mask_string.find("0")==mask_string.rfind("1")+1
4.判断IP是否属于私有IP地址;因为私有IP地址和A/B/C/D/E类地址不冲突,因此应当独立计算;
def private_check(IP): if IP[0]=="10": return True elif IP[0]=="172" and 16<=int(IP[1])<=31: return True elif IP[0]=="192" and IP[1]=="168": return True else: return False
5.判断IP属于哪一种类,并根据第一位的数值分类。在流程中,我们先判断IP是否符合基本格式,再进行种类的判断,因此每一位必然在0~255之间,所以除开ABCD以外的一定是E类,可以少写一个判断语句。
完整代码:
import sys A = 0 B = 0 C = 0 D = 0 E = 0 F = 0 # 错误IP或错误掩码 P = 0 # 私有IP #定义判断函数 def IP_check(IP): #对IP的基本检查:如果长度不为4或者某位数字不在0-255之间,说明格式不对 if len(IP)!=4: return False for i in IP: if not i.isnumeric(): #不是数字的情况 return False i=int(i) if i<0 or i>255: return False return True def mask_check(mask): #对掩码的基本检查:全为1/全为0/0后有1均为非法 if not IP_check(mask):#掩码也要满足长度为4,每位在0-255之间的要求 return False mask_string="" for m in mask: ms=bin(int(m))[2:] mask_string+=ms.zfill(8) #.zfill:返回指定长度的字符串,原字符串右对齐,前面填充0 #找最后一个1和第一个0的位置;如果相差不是1则0后必有1,如果只有0或只有1,必然不可能相等(返回-1) return mask_string.find("0")==mask_string.rfind("1")+1 def private_check(IP): if IP[0]=="10": return True elif IP[0]=="172" and 16<=int(IP[1])<=31: return True elif IP[0]=="192" and IP[1]=="168": return True else: return False for line in sys.stdin: line = line.rstrip("\n") a = line.split("~") # 优先处理应该跳过的 IP = a[0].split(".") if IP[0] == "0" or IP[0] == "127": continue #判断是否为非法地址 if not IP_check(IP): F+=1 continue #判断是否为非法掩码 if not mask_check(a[1].split(".")): F+=1 continue #IP地址和掩码都正确,进行分类 if private_check(IP): P+=1 head=int(IP[0]) if 1<=head<=126: A+=1 elif 128<=head<=191: B+=1 elif 192<=head<=223: C+=1 elif 224<=head<=239: D+=1 else: E+=1 print(A,B,C,D,E,F,P)