题解 | #识别有效的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) }