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

