题解 | #判断两个IP是否属于同一子网#
判断两个IP是否属于同一子网
http://www.nowcoder.com/practice/34a597ee15eb4fa2b956f4c595f03218
思路:
- 判断ip和子网掩码的合法性。
- 然后通过&来获得子网掩码。
- 比较两个子网号是否一样。
由于Golang不像C和C++一样,能很好的操作底层,不能很好的将4个字节总体进行按位操作,因此把IP抽象一下,直接操作四个数,这样是比较简单。 另外,IP地址违法,这个题目也比较笼统,我随便输入一个字符串,我也可以说是违法的IP地址。考虑太多,这个题就不好做了。根据例子,非法的IP地址,一般就是字节不在0~255之间,子网掩码的合法性稍微复杂点。抽象成四个数后,每个数都是有限制的,当后面的数有值时,前面的数必须是255。最后面的一个数,必须是0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00中的某一个,这些数,是根据子网掩码的位限制得出来的。
package main
import (
"fmt"
)
type ipaddr struct {
byte1 int
byte2 int
byte3 int
byte4 int
}
type info struct {
mark string
ip1 string
ip2 string
netmark ipaddr
ipaddr1 ipaddr
ipaddr2 ipaddr
}
func main() {
var in info
for _, err := fmt.Scanf("%s\n", &in.mark); err == nil; _, err = fmt.Scanf("%s\n", &in.mark) {
fmt.Scanf("%s\n", &in.ip1)
fmt.Scanf("%s\n", &in.ip2)
fmt.Sscanf(in.mark, "%d.%d.%d.%d", &in.netmark.byte1, &in.netmark.byte2, &in.netmark.byte3, &in.netmark.byte4)
fmt.Sscanf(in.ip1, "%d.%d.%d.%d", &in.ipaddr1.byte1, &in.ipaddr1.byte2, &in.ipaddr1.byte3, &in.ipaddr1.byte4)
fmt.Sscanf(in.ip2, "%d.%d.%d.%d", &in.ipaddr2.byte1, &in.ipaddr2.byte2, &in.ipaddr2.byte3, &in.ipaddr2.byte4)
if !in.netmark.subnet_valid() || !in.ipaddr1.ip_valid() || !in.ipaddr2.ip_valid() {
fmt.Println("1")
continue
}
if in.same_network() {
fmt.Println("0")
continue
}
fmt.Println("2")
}
}
func (ip *ipaddr) ip_valid() bool {
r1 := (ip.byte1 <= 0 || ip.byte1 > 255)
r2 := (ip.byte2 < 0 || ip.byte2 > 255)
r3 := (ip.byte3 < 0 || ip.byte3 > 255)
r4 := (ip.byte4 < 0 || ip.byte4 > 255)
if r1 || r2 || r3 || r4 {
return false
}
return true
}
func (ip *ipaddr) subnet_valid() bool {
if ip.byte1 < ip.byte2 || ip.byte2 < ip.byte3 || ip.byte3 < ip.byte4 {
return false
}
if ip.byte4 != 0 {
if ip.byte3 != 0xff {
return false
}
}
if ip.byte3 != 0 {
if ip.byte2 != 0xff {
return false
}
}
if ip.byte2 != 0 {
if ip.byte1 != 0xff {
return false
}
}
if !ip_byte_check(ip.byte1) || !ip_byte_check(ip.byte2) || !ip_byte_check(ip.byte3) || !ip_byte_check(ip.byte4) {
return false
}
return true
}
func ip_byte_check(b int) bool {
if b == 0xff || b == 0xfe || b == 0xfc || b == 0xf8 || b == 0xf0 || b == 0xe0 || b == 0xc0 || b == 0x80 || b == 0x00 {
return true
}
return false
}
func (ip *ipaddr) get_subnet(ip1, ip2 ipaddr) (ipaddr, ipaddr) {
var net1 ipaddr
var net2 ipaddr
net1.byte1 = ip.byte1 & ip1.byte1
net1.byte2 = ip.byte2 & ip1.byte2
net1.byte3 = ip.byte3 & ip1.byte3
net1.byte4 = ip.byte4 & ip1.byte4
net2.byte1 = ip.byte1 & ip2.byte1
net2.byte2 = ip.byte2 & ip2.byte2
net2.byte3 = ip.byte3 & ip2.byte3
net2.byte4 = ip.byte4 & ip2.byte4
return net1, net2
}
func (i *info) same_network() bool {
net1, net2 := i.netmark.get_subnet(i.ipaddr1, i.ipaddr2)
if net1.byte1 == net2.byte1 && net1.byte2 == net2.byte2 && net1.byte3 == net2.byte3 && net1.byte4 == net2.byte4 {
return true
}
return false
}