题解 | #判断两个IP是否属于同一子网#

判断两个IP是否属于同一子网

http://www.nowcoder.com/practice/34a597ee15eb4fa2b956f4c595f03218

思路:

  1. 判断ip和子网掩码的合法性。
  2. 然后通过&来获得子网掩码。
  3. 比较两个子网号是否一样。

由于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
}
全部评论

相关推荐

菜菜咪:1. 可以使用简历网站的模版,美观度会更好一点 2. 邮箱可以重新申请一个,或者用qq邮箱的别名,部分hr可能会不喜欢数字邮箱 3. 项目经历最好分点描述,类似的项目很多,可以参考一下别人怎么写的 4. 自我评价可加可不加,技术岗更看重技术。最后,加油,优秀士兵
点赞 评论 收藏
分享
11-18 09:44
Java
小白也想要offer:简历别放洋屁,搞不还还放错了,当然你投外企除外,以上纯属个人观点
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务