Appearance
HJ39 判断两个IP是否属于同一子网
本节目标:理解“HJ39 判断两个IP是否属于同一子网”的核心思路,并能把它用于实际开发或面试表达。 较难 通过率:18.16% 时间限制:1秒 空间限制:32M 知识点==字符串====模拟== 描述 IP地址是由4个0-255之间的整数构成的,用"."符号相连。 二进制的IP地址格式有32位,例如:10000011,01101011,00000011,00011000;每八位用十进制表示就是131.107.3.24 子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据。 子网掩码与IP地址结构相同,是32位二进制数,由1和0组成,且1和0分别连续,其中网络号部分全为“1”和主机号部分全为“0”。 你可以简单的认为子网掩码是一串连续的1和一串连续的0拼接而成的32位二进制数,左边部分都是1,右边部分都是0。 利用子网掩码可以判断两台主机是否在同一子网中。 若两台主机的IP地址分别与它们的子网掩码进行逻辑“与”运算(按位与/AND)后的结果相同,则说明这两台主机在同一子网中。
示例: I P 地址 192.168.0.1 子网掩码 255.255.255.0 转化为二进制进行运算: I P 地址 11000000.10101000.00000000.00000001 子网掩码 11111111.11111111.11111111.00000000 AND运算 11000000.10101000.00000000.00000000 转化为十进制后为: 192.168.0.0
I P 地址 192.168.0.254 子网掩码 255.255.255.0
转化为二进制进行运算: I P 地址 11000000.10101000.00000000.11111110 子网掩码 11111111.11111111.11111111.00000000 AND运算 11000000.10101000.00000000.00000000 转化为十进制后为: 192.168.0.0 通过以上对两台计算机IP地址与子网掩码的AND运算后,我们可以看到它运算结果是一样的。均为192.168.0.0,所以这二台计算机可视为是同一子网络。
输入一个子网掩码以及两个ip地址,判断这两个ip地址是否是一个子网络。 若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2。
注: 有效掩码与IP的性质为:
- 掩码与IP每一段在 0 - 255 之间
- 掩码的二进制字符串前缀为网络号,都由‘1’组成;后缀为主机号,都由'0'组成 输入描述: 3行输入,第1行是输入子网掩码、第2,3行是输入两个ip地址 题目的示例中给出了三组数据,但是在实际提交时,你的程序可以只处理一组数据(3行)。 输出描述: 若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2 示例1 输入: 255.255.255.0192.168.224.256192.168.10.4 255.0.0.0193.194.202.15232.43.7.59 255.255.255.0192.168.0.254192.168.0.1
输出: 120
说明: 对于第一个例子:255.255.255.0192.168.224.256192.168.10.4其中IP:192.168.224.256不合法,输出1
对于第二个例子:255.0.0.0193.194.202.15232.43.7.592个与运算之后,不在同一个子网,输出2
对于第三个例子,2个与运算之后,如题目描述所示,在同一个子网,输出0
- {:08b}是一个格式说明符。:引入格式说明符,08表示结果字符串应该有8个字符宽,不足部分用0填充(这就是确保前导零的部分),b表示二进制格式。
- .format(int(i))是将int(i)(i字符串的整数形式)格式化为上述说明符指定的格式的方法。对于列表intList中的每个元素i,都将执行这个操作。
- ["{:08b}".format(int(i)) for i in intList]是一个列表推导式,它遍历intList,将每个元素转换为8位的二进制字符串,然后这些字符串被组成一个列表。
- ".join([...])`方法将前面步骤生成的列表中的所有字符串连接成一个单一的字符串,其中每个部分之间没有任何分隔符。
'{:8b}'和'{:08b}'有什么区别 在Python的字符串格式化中,{:8b}和{:08b}都用于将整数格式化为二进制字符串,但它们在处理前导零方面有所不同:
{:8b}:这个格式说明符表示转换成的二进制字符串至少占用8位宽度。如果转换后的二进制数位数少于8位,它将使用空格填充剩余的位数,直到总宽度达到8位。这意味着,如果你转换的数字较小,导致二进制表示不足8位,那么结果字符串的前面将会用空格填充。{:08b}:这个格式说明符同样表示转换成的二进制字符串至少占用8位宽度,但与上一个不同的是,如果二进制数位数少于8位,它将使用0而不是空格来填充剩余的位数,直到总宽度达到8位。这种方式确保了二进制字符串总是8位长,对于需要固定长度的二进制数据表示,如IP地址的每一段,这是非常有用的。
举例说明
假设我们要格式化数字5为二进制字符串:
- 使用
{:8b}格式化,得到的结果可能是' 101'(前面有5个空格)。 - 使用
{:08b}格式化,得到的结果是'00000101'。
对于网络编程和处理需要固定长度二进制表示的场合,如IP地址处理,{:08b}是更合适的选择,因为它保证了二进制字符串的长度,易于后续的处理和计算。
def check_ip_or_mask(parts):
检查IP地址或子网掩码的每个部分是否在0到255之间
return all(0 <= int(p) <= 255 for p in parts)
def is_valid_mask(mask):
将子网掩码转换为二进制字符串
bin_mask = ''.join(['{:08b}'.format(int(part)) for part in mask])
找到第一个0出现的位置
first_zero_index = bin_mask.find('0')
确保从第一个0之后不再出现1
return '1' not in bin_mask[first_zero_index:]
while True: try: mask = input().split(".") ip1 = input().split(".") ip2 = input().split(".") if not (check_ip_or_mask(mask) and check_ip_or_mask(ip1) and check_ip_or_mask(ip2) and is_valid_mask(mask)): print("1") continue def get_bin(intList): return "".join(["{:08b}".format(int(i)) for i in intList]) def is_same_net(mask, ip1, ip2): bin_mask = int(get_bin(mask), 2) p1_net = int(get_bin(ip1), 2) & bin_mask p2_net = int(get_bin(ip2), 2) & bin_mask print(0 if p1_net == p2_net else 2) is_same_net(mask, ip1, ip2) except EOFError: break
