题解 | #识别有效的IP地址和掩码并进行分类统计#

识别有效的IP地址和掩码并进行分类统计

https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682

/**
 * 1. Mask 255.255.255.255 , 0.0.0.0 为非法。
 * 2. IP和Mask必须同时正确,才能被分类到A, B, C, D, E以及私有。
 * 3. IP和Mask同时错误时,只算一次错误
 * 4. 注意0.*.*.*以及127.*.*.*不属于任何类别。
 * 5. 不能把字符串和数字一样做比较: "53" > "123" // true
 */
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	cnt := map[byte]int{}

	sc := bufio.NewScanner(os.Stdin)
	for sc.Scan() {
		s := sc.Text()
		sp := strings.Split(s, "~")
		if strings.HasPrefix(sp[0], "0.") || strings.HasPrefix(sp[0], "127.") {
			continue
		}

		ip := parse(sp[0])
		mask := parse(sp[1])
		kind, private := CheckIp(ip)
		isMask := CheckMask(mask)

		if isMask {
			cnt[kind]++
			if private {
				cnt['g']++
			}
		} else {
			if kind != 'n' {
				cnt['f']++
			}
		}
	}

	fmt.Printf("%d %d %d %d %d %d %d", cnt['a'], cnt['b'], cnt['c'], cnt['d'], cnt['e'], cnt['f'], cnt['g'])
}

func CheckIp(ip []int) (byte, bool) {
	if !IsOk(ip) {
		return 'f', false
	}

	if ip[0] >= 0 && ip[0] <= 126 {
		return 'a', ip[0] == 10
	}

	if ip[0] >= 128 && ip[0] <= 191 {
		return 'b', ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31
	}

	if ip[0] >= 192 && ip[0] <= 223 {
		return 'c', ip[0] == 192 && ip[1] == 168
	}

	if ip[0] >= 224 && ip[0] <= 239 {
		return 'd', false
	}
	if ip[0] >= 240 && ip[0] <= 255 {
		return 'e', false
	}

	return 'n', false
}

func CheckMask(ip []int) bool {
	if ip == nil {
		return false
	}
	var res uint32
	for i := 0; i < len(ip); i++ {
		res = res<<8 + uint32(ip[i])
	}

	if res == 0 || res == 0xffffffff {
		return false
	}

	const high = 0x80000000
	for {
		if (res & high) == 0 {
			break
		}
		res = res << 1
	}
	return res == 0
}

func IsOk(ip []int) bool {
	if ip == nil {
		return false
	}
	res := true
	for i := 0; i < len(ip); i++ {
		res = res && ip[1] >= 0 && ip[i] <= 255
	}

	return res
}

func parse(s string) []int {
	sp := strings.Split(s, ".")
	if len(sp) != 4 {
		return nil
	}

	res := []int{}
	for i := 0; i < 4; i++ {
		val, err := strconv.Atoi(sp[i])
		if err != nil {
			return nil
		}
		res = append(res, val)
	}
	return res
}

错误示例:

package main

import (
	"fmt"
	"strings"
)

func main() {
	var input string
	ipCount := make([]int, 7) // A, B, C, D, E, 错误IP地址或错误掩码, 私有IP
	privateIPRanges := []string{"10.", "172.", "192.168."}

	for {
		_, err := fmt.Scanln(&input)
		if err != nil {
			break
		}

		ip, mask := parseInput(input)
		if isValidIP(ip) && isValidMask(mask) {
			if isPrivateIP(ip, privateIPRanges) {
				ipCount[6]++
			} else if isClassA(ip) {
				ipCount[0]++
			} else if isClassB(ip) {
				ipCount[1]++
			} else if isClassC(ip) {
				ipCount[2]++
			} else if isClassD(ip) {
				ipCount[3]++
			} else if isClassE(ip) {
				ipCount[4]++
			}
		} else {
			ipCount[5]++
		}
	}

	fmt.Println(strings.Trim(fmt.Sprint(ipCount), "[]"))
}

func parseInput(input string) (string, string) {
	parts := strings.Split(input, "~")
	return parts[0], parts[1]
}

func isValidIP(ip string) bool {
	octets := strings.Split(ip, ".")
	if len(octets) != 4 {
		return false
	}

	for _, octet := range octets {
		if octet == "" {
			return false
		}

		num := 0
		for _, digit := range octet {
			if digit < '0' || digit > '9' {
				return false
			}
			num = num*10 + int(digit-'0')
		}

		if num < 0 || num > 255 {
			return false
		}
	}

	return true
}

func isValidMask(mask string) bool {
	octets := strings.Split(mask, ".")
	if len(octets) != 4 {
		return false
	}

	maskBinary := ""
	for _, octet := range octets {
		if octet == "" {
			return false
		}

		num := 0
		for _, digit := range octet {
			if digit < '0' || digit > '9' {
				return false
			}
			num = num*10 + int(digit-'0')
		}

		if num < 0 || num > 255 {
			return false
		}

		binary := fmt.Sprintf("%08b", num)
		maskBinary += binary
	}

	ones := strings.Index(maskBinary, "0")
	zeros := strings.Index(maskBinary, "1")

	if ones != -1 && zeros != -1 && ones < zeros {
		return false
	}

	return true
}

func isPrivateIP(ip string, privateIPRanges []string) bool {
	for _, rangePrefix := range privateIPRanges {
		if strings.HasPrefix(ip, rangePrefix) {
			return true
		}
	}
	return false
}

func isClassA(ip string) bool {
	octets := strings.Split(ip, ".")
	firstOctet := octets[0]
	num := 0
	for _, digit := range firstOctet {
		num = num*10 + int(digit-'0')
	}
	return num >= 1 && num <= 126
}

func isClassB(ip string) bool {
	octets := strings.Split(ip, ".")
	firstOctet := octets[0]
	secondOctet := octets[1]
	num1 := 0
	num2 := 0
	for _, digit := range firstOctet {
		num1 = num1*10 + int(digit-'0')
	}
	for _, digit := range secondOctet {
		num2 = num2*10 + int(digit-'0')
	}
	return num1 == 128 && num2 >= 0 && num2 <= 191
}

func isClassC(ip string) bool {
	octets := strings.Split(ip, ".")
	firstOctet := octets[0]
	secondOctet := octets[1]
	num1 := 0
	num2 := 0
	for _, digit := range firstOctet {
		num1 = num1*10 + int(digit-'0')
	}
	for _, digit := range secondOctet {
		num2 = num2*10 + int(digit-'0')
	}
	return num1 == 192 && num2 >= 0 && num2 <= 223
}

func isClassD(ip string) bool {
	octets := strings.Split(ip, ".")
	firstOctet := octets[0]
	num := 0
	for _, digit := range firstOctet {
		num = num*10 + int(digit-'0')
	}
	return num >= 224 && num <= 239
}

func isClassE(ip string) bool {
	octets := strings.Split(ip, ".")
	firstOctet := octets[0]
	num := 0
	for _, digit := range firstOctet {
		num = num*10 + int(digit-'0')
	}
	return num >= 240 && num <= 255
}

package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main() {
	var input string
	fmt.Scan(&input)

	ipList := strings.Split(input, "\n")

	aCount := 0
	bCount := 0
	cCount := 0
	dCount := 0
	eCount := 0
	errorCount := 0
	privateCount := 0

	for _, ip := range ipList {
		parts := strings.Split(ip, "~")
		if len(parts) != 2 {
			errorCount++
			continue
		}

		addr := parts[0]
		mask := parts[1]

		if !isValidIP(addr) || !isValidMask(mask) {
			errorCount++
			continue
		}

		if isPrivateIP(addr) {
			privateCount++
		}

		ipInt := ipToInt(addr)
		// maskInt := maskToInt(mask)

		if ipInt >= 1 && ipInt <= 126 {
			aCount++
		} else if ipInt >= 128 && ipInt <= 191 {
			bCount++
		} else if ipInt >= 192 && ipInt <= 223 {
			cCount++
		} else if ipInt >= 224 && ipInt <= 239 {
			dCount++
		} else if ipInt >= 240 && ipInt <= 255 {
			eCount++
		}
	}

	fmt.Println(aCount, bCount, cCount, dCount, eCount, errorCount, privateCount)
}

func isValidIP(ip string) bool {
	parts := strings.Split(ip, ".")
	if len(parts) != 4 {
		return false
	}

	for _, part := range parts {
		if part == "" {
			return false
		}

		num, err := strconv.Atoi(part)
		if err != nil || num < 0 || num > 255 {
			return false
		}
	}

	return true
}

func isValidMask(mask string) bool {
	parts := strings.Split(mask, ".")
	if len(parts) != 4 {
		return false
	}

	for _, part := range parts {
		if part == "" {
			return false
		}

		num, err := strconv.Atoi(part)
		if err != nil || num < 0 || num > 255 {
			return false
		}

		bin := strconv.FormatInt(int64(num), 2)
		if !strings.HasPrefix(bin, "1") || !strings.HasSuffix(bin, "0") {
			return false
		}
	}

	return true
}

func isPrivateIP(ip string) bool {
	parts := strings.Split(ip, ".")
	if len(parts) != 4 {
		return false
	}

	first, _ := strconv.Atoi(parts[0])
	second, _ := strconv.Atoi(parts[1])

	if first == 10 {
		return true
	}

	if first == 172 && second >= 16 && second <= 31 {
		return true
	}

	if first == 192 && second == 168 {
		return true
	}

	return false
}

func ipToInt(ip string) int {
	parts := strings.Split(ip, ".")
	if len(parts) != 4 {
		return 0
	}

	var result int

	for _, part := range parts {
		num, _ := strconv.Atoi(part)
		result = result*256 + num
	}

	return result
}

func maskToInt(mask string) int {
	parts := strings.Split(mask, ".")
	if len(parts) != 4 {
		return 0
	}

	var result int

	for _, part := range parts {
		num, _ := strconv.Atoi(part)
		result = result*256 + num
	}

	return result
}

package main

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
)

func isValidIPAddress(ip string) bool {
	ipRegex := `^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`
	match, _ := regexp.MatchString(ipRegex, ip)
	return match
}

func isValidMask(mask string) bool {
	maskRegex := `^(?:255|254|252|248|240|224|192|128|0)+\.(?:255|254|252|248|240|224|192|128|0)+\.(?:255|254|252|248|240|224|192|128|0)+\.(?:255|254|252|248|240|224|192|128|0)+$`
	match, _ := regexp.MatchString(maskRegex, mask)
	if !match {
		return false
	}
	ipSegments := strings.Split(mask, ".")
	binaryMask := ""
	for _, segment := range ipSegments {
		i, _ := strconv.Atoi(segment)
		binarySegment := strconv.FormatInt(int64(i), 2)
		binaryMask += binarySegment
	}
	allOnes := true
	for i := 1; i < len(binaryMask); i++ {
		if binaryMask[i] == '0' {
			allOnes = false
			break
		}
	}
	return allOnes
}

func classifyIPAddresses(input string) (int, int, int, int, int, int, int) {
	lines := strings.Split(input, "\n")
	aCount := 0
	bCount := 0
	cCount := 0
	dCount := 0
	eCount := 0
	errorCount := 0
	privateCount := 0
	for _, line := range lines {
		ipAndMask := strings.Split(line, "~")
		ip := ipAndMask[0]
		mask := ipAndMask[1]
		if !isValidIPAddress(ip) || !isValidMask(mask) {
			errorCount++
			continue
		}
		ipSegments := strings.Split(ip, ".")
		firstSegment, _ := strconv.Atoi(ipSegments[0])
		switch {
		case firstSegment >= 1 && firstSegment <= 126:
			aCount++
		case firstSegment >= 128 && firstSegment <= 191:
			bCount++
		case firstSegment >= 192 && firstSegment <= 223:
			cCount++
		case firstSegment >= 224 && firstSegment <= 239:
			dCount++
		case firstSegment >= 240 && firstSegment <= 255:
			eCount++
		}
		if (firstSegment == 10) || (firstSegment == 172 && (ipSegments[1] >= "16" && ipSegments[1] <= "31")) || (firstSegment == 192 && ipSegments[1] == "168") {
			privateCount++
		}
	}
	return aCount, bCount, cCount, dCount, eCount, errorCount, privateCount
}

func main() {
	input := "10.70.44.68~255.254.255.0\n1.0.0.1~255.0.0.0\n192.168.0.2~255.255.255.0\n19..0.~255.255.255.0"
	aCount, bCount, cCount, dCount, eCount, errorCount, privateCount := classifyIPAddresses(input)
	fmt.Printf("%d %d %d %d %d %d %d\n", aCount, bCount, cCount, dCount, eCount, errorCount, privateCount)
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-03 16:22
点赞 评论 收藏
分享
06-19 19:06
门头沟学院 Java
码农索隆:别去东软,真学不到东西,真事
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务