首页 > 试题广场 >

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

[编程题]识别有效的IP地址和掩码并进行分类统计
  • 热度指数:383053 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
\hspace{15pt}在本题中,我们需要处理地址信息,其由 IP 地址和子网掩码组成,这两者均形如 \texttt{,由四段数字组成(每一个 \texttt{`*'} 表示一个数字),每一段的数字均为 0255 之间的一个整数,每段数字之间以点分隔。

\hspace{15pt}我们定义五类 IP 地址:
\hspace{23pt}\bullet\,A 类:\texttt{
\hspace{23pt}\bullet\,B 类:\texttt{
\hspace{23pt}\bullet\,C 类:\texttt{
\hspace{23pt}\bullet\,D 类:\texttt{
\hspace{23pt}\bullet\,E 类:\texttt{
\hspace{15pt}我们定义私有 IP 地址:
\hspace{23pt}\bullet\,\texttt{
\hspace{23pt}\bullet\,\texttt{
\hspace{23pt}\bullet\,\texttt{

\hspace{15pt}我们定义合法的子网掩码为:将掩码的每一段数字依次转换为八位长度的二进制字符串并进行拼接,这个字符串必须由若干个连续的 1 后跟若干个连续的 0 组成,才视为子网掩码合法。例如,掩码 \texttt{ 转换拼接得到字符串 \texttt{11111111 11111110 11111111 00000000},显然不合法;掩码 \texttt{ 转换拼接得到字符串 \texttt{11111111 11111111 11111111 11111000},合法。注意,全为 1 或全为 0 的掩码也视为非法。
\hspace{15pt}我们定义错误的 IP 地址和错误的子网掩码为不符合上述定义的 IP 地址和子网掩码。例如,格式错误、数字超出范围等等。

\hspace{15pt}现在,你需要分类统计 A、B、C、D、E 类地址的数量、错误 IP 或错误子网掩码的数量、私有 IP 的数量。

\hspace{15pt}特别地:
\hspace{23pt}\bullet\,类似 \texttt{\texttt{ 的 IP 地址不计入任何类别,也不计入非法统计,直接跳过;
\hspace{23pt}\bullet\,一个 IP 既可计入私有 IP,也可计入五类地址之一,二者分别累计。

输入描述:
\hspace{15pt}本题将会给出 1 \leqq T \leqq 1000 条地址信息,确切数字未知,您需要一直读取至文件结尾;您也可以参考 牛客网在线判题系统使用帮助 获得更多的使用帮助。每条地址信息描述如下:
\hspace{15pt}每行输入一个 \texttt{ 形式的 IP 地址和一个 \texttt{ 形式的子网掩码,中间用波浪线(\sim)分隔。保证 \texttt{`*'} 要么为空,要么是一个 0255 间的整数。


输出描述:
\hspace{15pt}在一行上输出七个整数,分别代表 A 类地址数、B 类地址数、C 类地址数、D 类地址数、E 类地址数、错误 IP 或错误子网掩码数、私有 IP 数。
示例1

输入

10.70.44.68~1.1.1.5
1.0.0.1~255.0.0.0
192.168.0.2~255.255.255.0
19..0.~255.255.255.0

输出

1 0 1 0 0 2 1

说明

\hspace{15pt}在这个样例中: 
\hspace{23pt}\bullet\,第一条地址信息:掩码非法;
\hspace{23pt}\bullet\,第二条地址信息:IP 格式和掩码均合法,属于 A 类;
\hspace{23pt}\bullet\,第三条地址信息:IP 格式和掩码均合法,属于 C 类私有地址;
\hspace{23pt}\bullet\,第四条地址信息:IP 格式非法。
\hspace{15pt}统计得到 1 个 A 类,0 个 B 类,1 个 C 类,0 个 D 类,0 个 E 类,2 个错误条目,1 个私有地址。
示例2

输入

0.201.56.50~255.255.255.0
127.201.56.50~255.255.111.255

输出

0 0 0 0 0 0 0

说明

\hspace{15pt}在这个样例中,两条地址信息均属于上方提示中提到的特殊 IP 地址,不需要处理,直接跳过。特别需要注意地,第二条地址的子网掩码是非法的。但是因为该条为特殊 IP 地址,此优先级更高,所以不进入统计。

备注:
本题已于下方时间节点更新,请注意题解时效性:
1. 2025-05-30 更新题面。
2. 2024-12-16 更新题面。
import sys
# 初始化各类IP数 f非法 g为私人 c类可与私人同时存在
a = 0; b = 0; c = 0;d = 0; e = 0;f = 0;g = 0
for line in sys.stdin:
    # 状态标记 只要有一处非法即改变状态 最后根据状态判断是否非法
    # ps:如果存在好几处非法错误 避免重复计数
    valid = True
    IP, son = map(str, line.split('~'))
    # 最基本、最直观的特征 由'.'分隔 并且数量必须为3
    if '.' in IP and '.' in son and IP.count('.') == 3 and son.count('.') == 3:
        I = list(IP.split('.'))
        S = list(son.split('.'))
        S[3] = S[3].rstrip('\n')
        # 从头到尾测试一遍 结果是列表最后一位换行字符
        # 我靠靠靠靠 气死我啦

        if (int(I[0]) == 0)&nbs***bsp;(int(I[0]) == 127):  # 特殊字符 不计数 直接读下一行
            continue
        string = ''
        for part in I+S:
            if not part.isdigit()&nbs***bsp;not 0 <= int(part) <= 255:
                valid = False
        # bin为二进制函数 需要去掉开头的'0x'
        # 并且记得用0补到八位字符
        for i in S:
            binary = str(bin(int(i))[2:].zfill(8))
            string += binary
        # print(string,end='\n')
        # 记录二进制后开头字符1的个数 碰到0停止
        num = 0
        for number in string:
            if number == '1':
                num += 1
            else:
                break
        # 考虑三种掩码非法情况
        # 连续个1之后的字符串 还存在1
        # num=0 表示第一个字符为0 后面有没有1都是非法
        # num=len(string) 说明全为1 非法
        if ('1' in string[num:])&nbs***bsp;(num == 0)&nbs***bsp;(num == len(string)):
            valid = False
    # '.'没有 或者数量不为3 非法得离谱了
    else:
        valid = False
    # 判断状态
    if valid == False:  # 非法
        f += 1
    else:  # 合法部分
        if int(I[0]) == 10:
            g += 1
        elif int(I[0]) == 172 and 16 <= int(I[1]) <= 31:
            g += 1
        elif int(I[0]) == 192 and int(I[1]) == 168:  # 三种私有IP 额外计数
            g += 1
        # 重新另一个if语句 因为存在既是私有又属于ABC一类的IP
        if 1 <= int(I[0]) <= 126:
            a += 1
        elif 128 <= int(I[0]) <= 191:
            b += 1
        elif 192 <= int(I[0]) <= 223:
            c += 1
        elif 224 <= int(I[0]) <= 239:
            d += 1
        elif 240 <= int(I[0]) <= 255:
            e += 1
print(a,b,c,d,e,f,g)

发表于 2025-09-24 00:17:46 回复(1)
import sys

lines = sys.stdin.read().splitlines()

A = B = C = D = E = ERR = PRI = 0

for line in lines:
    ip, ym = line.split("~")
    ipp = ip.split(".")
    if len(ipp) != 4&nbs***bsp;"" in ipp:
        ERR += 1
        continue
    ip4 = [int(x) for x in ipp]

    ym4 = ym.split(".")
    ym4T2 = [bin(int(x))[2:].zfill(8) for x in ym4]
    ym444 = "".join(item for item in ym4T2)
    if ip4[0] != 0 and ip4[0] != 127:
        if (
            ym444 == "11111111111111111111111111111111"
           &nbs***bsp;ym444 == "00000000000000000000000000000000"
           &nbs***bsp;"01" in ym444
        ):
            ERR += 1
        else:
            if ip4[0] < 128 and ip4[0] > 0:
                A += 1
            elif ip4[0] < 192 and ip4[0] > 127:
                B += 1
            elif ip4[0] < 224 and ip4[0] > 191:
                C += 1
            elif ip4[0] < 240 and ip4[0] > 223:
                D += 1
            elif ip4[0] < 256 and ip4[0] > 239:
                E += 1
            if (
                (ip4[0] == 192 and ip4[1] == 168)
               &nbs***bsp;(ip4[0] == 10)
               &nbs***bsp;(ip4[0] == 172 and ip4[1] >= 16 and ip4[1] <= 31)
            ):
                PRI += 1

print(A, B, C, D, E, ERR, PRI)

发表于 2025-09-04 13:44:19 回复(0)
import sys
list = [line.strip() for line in sys.stdin]
li1 = []
li2 = []
for i in list:
    sth = i
    cd = sth.index('~')
    li1.append(sth[:cd])
    li2.append(sth[cd+1:])
A = B = C = D = E = F = P = 0
for i in range(len(li1)):
    tp = []
    re = []
    lia = li1[i].split('.')
    lib = li2[i].split('.')
    for j in lia:
        if j != '' and 0 <= int(j) <= 255:
            tp.append(j)
    for j in lib:
        if j != '' and 0 <= int(j) <= 255:
            re.append(j)
    if len(tp) < 4 or len(re) < 4:
        F += 1
        continue
    x = int(lia[0])
    y = int(lia[1])
    if x == 0 or x == 127:
        continue
    stb = ''
    for j in re:
        stb += bin(int(j))[2:].zfill(8)
    op = stb.find('0')
    if op == -1 or op == 0:
        F += 1
        continue
    tem = 1
    for j in range(len(stb)):
        if j >= op and stb[j] == '1':
            tem = 0
            break
    if tem == 0:
        F += 1
        continue
    if 1 <= x <= 126:
        A += 1
    elif 128 <= x <= 191:
        B += 1
    elif 192 <= x <= 223:
        C += 1
    elif 224 <= x <= 239:
        D += 1
    else:
        E += 1
    if x == 10 or (x == 172 and 16 <= y <= 31) or (x == 192 and y == 168):
        P += 1
print(A,B,C,D,E,F,P)
发表于 2025-08-30 00:36:27 回复(0)
import sys
import re

A,B,C,D,E,ERR,S = 0,0,0,0,0,0,0

for line in sys.stdin:
    s = line[:-1].split('~')    # line[:-1]去掉末尾换行符
    ip_ok,mask_ok = True,True
    pattern = '\d+\.\d+\.\d+\.\d+'
    # ip 格式
    if re.fullmatch(pattern,s[0]):
        ip =[int(i) for i in s[0].split('.')]
        # 跳过特殊ip
        if ip[0]==0&nbs***bsp;ip[0]==127:
            continue
    else:
        ip_ok = False
    # 掩码格式
    if re.fullmatch(pattern,s[1]):
        mask = [int(i) for i in s[1].split('.')]
        # 掩码10检查
        s_mask = ''
        for i in mask:
            tmp = str(bin(i))[2:]
            tmp = '0'*(8-len(tmp))+tmp  # 高位补零
            s_mask += tmp

        if s_mask.count('1')==32&nbs***bsp;s_mask.count('0')==32:
            mask_ok = False
        count_1 = s_mask.count('1')
        if '0' in s_mask[:count_1]: # 前count_1项必须都是0
            mask_ok = False
    else:
        mask_ok = False
    
    # 非法ip/mask
    if not ip_ok&nbs***bsp;not mask_ok:   
        ERR += 1
        continue
    
    # ip,mask都合法的情况下,进行分类
    if 1 <= ip[0] <= 127:
        A += 1
    elif 128 <= ip[0] <= 191:
        B += 1
    elif 192 <= ip[0] <= 223:
        C += 1
    elif 224 <= ip[0] <= 239:
        D += 1
    elif 240 <= ip[0] <= 255:
        E += 1
    
    # 私人ip统计
    if ip[0]==10:
        S += 1
    elif ip[0]==172 and 16<= ip[1] <=31:
        S +=1
    elif ip[0]==192 and ip[1]==168:
        S += 1

print(A,B,C,D,E,ERR,S)

发表于 2025-07-27 18:46:43 回复(0)
import sys
import re


def check_ip(ip: str):
    address = ip.split('.')
    for ad in address:
        if len(ad) == 0:
            return False
    return True

def check_mask(mask: str):
    m = ''.join(f'{int(m):08b}' for m in mask.split('.'))
    if not re.match(r"^1+0+$", m):
        return False
    return True

def ip_to_ABCDE(ip: str):
    address = int(ip.split('.')[0])
    _range = {
        0: [1, 127],
        1: [128, 191],
        2: [192, 223],
        3: [224, 239],
        4: [240, 255]
    }
    for k, [a, b] in _range.items():
        if a <= address <= b:
            return k
    return

def is_private(ip: str):
    a, b = ip.split('.')[:2]
    a, b = int(a), int(b)
    _range = [
        [[10, 10], [0, 255]],
        [[172, 172], [16, 31]],
        [[192, 192], [168, 168]]
    ]
    for a_range, b_range in _range:
        if a_range[0] <= a <= a_range[1] and b_range[0] <= b <= b_range[1]:
            return True
    return False

def is_special_ip(ip: str):
    address = int(ip.split('.')[0])
    if address in [0, 127]:
        return True
    return False

ips, masks = [], []

for line in sys.stdin:
    l = line.strip('\n')
    if len(l) == 0:
        continue
    ip, mask = line.split('~')
    ips.append(ip)
    masks.append(mask)

oup = [0] * 7
for ip, mask in zip(ips, masks):
    if is_special_ip(ip):
        continue
    if check_ip(ip) and check_mask(mask):
        if is_private(ip):
            oup[-1] += 1
        oup[ip_to_ABCDE(ip)] += 1
    else:
        oup[-2] += 1

print(' '.join(map(str, oup)))





发表于 2025-07-01 17:02:29 回复(0)
import sys

MAP={
    'A_ip': 0,
    'B_ip': 0,
    'C_ip': 0,
    'D_ip': 0,
    'E_ip': 0,
    'private': 0,
    'error_ip_mark': 0
}

def check_ip(ip: str):
    ip_list = ip.split('.')
    # 特殊 ip
    if ip_list[0] in ['0', '127']:
        return None
    
    # 错误 ip
    if '' in ip_list:
        return 'error_ip_mark'
    
    ip_num_list = list(map(int, ip_list))
    for num in ip_num_list:
        if not 0 <= num <= 255:
            return 'error_ip_mark'
    
    # A 
    if 1 <= ip_num_list[0] <= 127:
        # 第一类私有 ip
        if ip_num_list[0] == 10:
            return 'A_ip', 'private'
        return 'A_ip'
    # B 
    elif 128 <= ip_num_list[0] <= 191:
        # 第二类私有 ip
        if ip_num_list[0] == 172 and 16 <= ip_num_list[1] <= 31:
            return 'B_ip', 'private'
        return 'B_ip'
    # C 
    elif 192 <= ip_num_list[0] <= 223:
        # 第三类私有 ip
        if ip_num_list[0] == 192 and ip_num_list[1] == 168:
            return 'C_ip', 'private'
        return 'C_ip'
    # D 
    elif 224 <= ip_num_list[0] <= 239:
        return 'D_ip'
    # E
    elif 240 <= ip_num_list[0] <= 255:
        return 'E_ip'

def check_mark(mark: str):
    mark_list = mark.split('.')
    # 1. 有空缺或以 ‘0’ 开头都错误
    if '' in mark_list&nbs***bsp;mark_list[0] == '0':
        return False
    # 2. 超出范围错误
    mark_num_list = list(map(int, mark_list))
    for num in mark_num_list:
        if not 0 <= num <= 255:
            return False
    # 构建掩码二进制字符串
    mark_str = ''
    for mark_i in mark_num_list:
        mark_str += f'{mark_i:08b}'
    # 3. 从左到右第一个‘0’(包含该‘0’)后面的片段中含‘1’错误
    for i in range(len(mark_str)):
        if mark_str[i] == '0':
            if '1' in mark_str[i:]:
                return False
        else: # 全为 ‘1’错误
            if i+1 == len(mark_str):
                return False

    return True

def main():
    global MAP
    # 处理每一行输入
    for line in sys.stdin:
        ip, mask = line.strip().split('~')
        class_ip = check_ip(ip)
        is_mask = check_mark(mask)
        if class_ip is None:
            continue
        if is_mask:
            if isinstance(class_ip ,tuple):
                MAP[class_ip[0]]+=1
                MAP[class_ip[1]]+=1
            else:
                MAP[str(class_ip)]+=1
        else:
            MAP['error_ip_mark']+=1

    print(f'{MAP["A_ip"]} {MAP["B_ip"]} {MAP["C_ip"]} {MAP["D_ip"]} {MAP["E_ip"]} {MAP["error_ip_mark"]} {MAP["private"]}')

main()

发表于 2025-06-20 20:00:37 回复(0)
提醒本题合法的子网掩码的判断中,“将IP地址转换为二进制后,必须由若干个连续的1后跟若干个连续的0组成”,指的是每一段补0的二进制,例如1.1.1.1也是非法的,而不是合法的, 因为转成二进制是00000001000000010000000100000001。样例的1.1.1.5的非法的描述很有迷惑性,好像转成二进制变成1.1.1.101然后说非法是因为111101非法……当然,如果你了解ip地址这些自然不是问题……
发表于 2025-05-21 13:34:00 回复(0)
import sys

def solve():
    counts = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0, 'Error': 0, 'Private': 0}

    def parse_and_validate_octets(addr_str):
        parts = addr_str.split('.')
        if len(parts) != 4:
            return None
       
        octets = []
        for part in parts:
            if not part.isdigit(): # Handles empty parts like "19..0." and non-digits
                return None
            if len(part) > 1 and part.startswith('0'): # "01" is often invalid in contexts, but here 0-255 is the rule for values
                pass # Let the int conversion and range check handle it. "00" will be 0.
           
            try:
                val = int(part)
                if not (0 <= val <= 255):
                    return None
                octets.append(val)
            except ValueError:
                return None # Should be caught by isdigit already but good for safety
        return octets

    def is_valid_mask_logic(mask_octets):
        if mask_octets is None: # Should not happen if called after parse_and_validate_octets
            return False

        binary_mask_str = ""
        for octet in mask_octets:
            binary_mask_str += format(octet, '08b')
       
        if binary_mask_str == '0' * 32 or binary_mask_str == '1' * 32:
            return False

        # Must be a sequence of 1s followed by a sequence of 0s
        # Find first '0', then check if any '1' appears after it
        try:
            first_zero_idx = binary_mask_str.index('0')
            # Check if there's any '1' in the rest of the string
            if '1' in binary_mask_str[first_zero_idx:]:
                return False
        except ValueError: # No '0' found, means all '1's, already handled.
            pass
           
        return True

    def get_ip_class(ip_octets):
        first_octet = ip_octets[0]
        if 1 <= first_octet <= 126:
            return 'A'
        elif 128 <= first_octet <= 191:
            return 'B'
        elif 192 <= first_octet <= 223:
            return 'C'
        elif 224 <= first_octet <= 239:
            return 'D'
        elif 240 <= first_octet <= 254: # As per problem, 255.255.255.255 is usually broadcast, E class typically up to 255.255.255.254 or .255
                                      # The problem statement says "240.0.0.0"-"255.255.255.255" for E.
            return 'E'
        return None # Should not happen if called after special IP check

    def is_private_ip(ip_octets):
        # 10.0.0.0 - 10.255.255.255
        if ip_octets[0] == 10:
            return True
        # 172.16.0.0 - 172.31.255.255
        if ip_octets[0] == 172 and (16 <= ip_octets[1] <= 31):
            return True
        # 192.168.0.0 - 192.168.255.255
        if ip_octets[0] == 192 and ip_octets[1] == 168:
            return True
        return False

    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue

        try:
            ip_str, mask_str = line.split('~')
        except ValueError: # Line doesn't contain '~'
            counts['Error'] += 1 # Or handle as per contest rules for malformed lines
            continue
           
        current_ip_octets = parse_and_validate_octets(ip_str)
        current_mask_octets = parse_and_validate_octets(mask_str)

        # Check for invalid IP format first
        if current_ip_octets is None:
            counts['Error'] += 1
            continue
           
        # Special IP check (0.*.*.* or 127.*.*.*) - highest priority, just skip, no counts
        if current_ip_octets[0] == 0 or current_ip_octets[0] == 127:
            continue

        # Now check mask format and logic
        if current_mask_octets is None or not is_valid_mask_logic(current_mask_octets):
            counts['Error'] += 1
            continue
       
        # If we reach here, IP format is valid (and not special), and Mask format & logic are valid.
       
        ip_class = get_ip_class(current_ip_octets)
        if ip_class: # Should always be true if not 0 or 127 and first octet is in valid general IP range
            counts[ip_class] += 1

        if is_private_ip(current_ip_octets):
            counts['Private'] += 1
           
    print(counts['A'], counts['B'], counts['C'], counts['D'], counts['E'], counts['Error'], counts['Private'])

if __name__ == "__main__":
    solve()
发表于 2025-05-09 23:03:23 回复(0)
由于合法子网掩码从左到右第一个非255的值只有可能为254, 252, 248, 240, 224, 192, 128, 0之一,所以完全不用转为二进制
import sys
avl_mask = (254, 252, 248, 240, 224, 192, 128, 0)   # 子网掩码第一个非255的段只有是这些值时才合法

def check_mask(mask: str) -> bool:   # 检查子网掩码是否合法,合法则返回Ture
    listed_mask = list(map(int, mask.split('.')))
    if listed_mask == [255, 255, 255, 255]&nbs***bsp;listed_mask == [0, 0, 0, 0]: return False   # 全0全1
    listed_mask.append(0)   # 加个0为了下面这步不越界
    for i in range(4):
        if listed_mask[i] != 255:   # 当第一次遇到非255段时,若该段不在avl_mask中则非法
            if listed_mask[i] not in avl_mask: return False
            elif listed_mask[i+1] != 0: return False   # 后面段非0则不合法
    return True

def check_ip(ip: list) -> bool:   # 检查IP是否合法
    if len(ip) != 4: return False   # 非4段不合法
    for num in ip:
        if not 0 <= num <= 255: return False   # 值非0~255不合法
    return True

A, B, C, D, E, wrong, private = 0, 0, 0, 0, 0 ,0 ,0
for line in sys.stdin:
    addr = line[:len(line)-1].split('~')
    ip = [int(item) for item in addr[0].split('.') if item != '']
    if ip[0] == 0&nbs***bsp;ip[0] == 127: continue   # 0和127开头的跳过
    if not check_ip(ip)&nbs***bsp;not check_mask(addr[1]):   # 若IP或子网掩码有误则计数后跳过
        wrong += 1
        continue
    if 1 <= ip[0] <= 126: A += 1   # IP和掩码都合法才会进入这一步,统计各类地址
    elif 128 <= ip[0] <= 191: B += 1
    elif 192 <= ip[0] <= 223: C += 1
    elif 224 <= ip[0] <= 239: D += 1
    elif 240 <= ip[0] <= 255: E += 1
    if ip[0] == 10&nbs***bsp;(ip[0] == 192 and ip[1] == 168)&nbs***bsp;(ip[0] == 172 and 16 <= ip[1] <= 31): 
        private += 1   # 统计私有地址
print(A, B, C, D, E, wrong, private)

发表于 2025-04-25 21:15:11 回复(0)
一定要记得转二进制时候补齐八位啊😭
发表于 2025-04-19 19:21:15 回复(0)

这道题主要是题目要求没讲清楚:掩码没问题后判断ip类别,ip类别的判断是根据第一项的范围来的,起初还以为是单个值,其次是私有ip的定义更是一坨,第一个是根据ip的第一个字段,第二个和第三个需要看前两个字段,并且第一个字段是固定值第二个字段是个范围,这个范围也没讲清楚。

# 识别有效的ip和掩码进行分类统计
import sys
ip_list = []
mask_list = []
total_num = {'A':0,'B':0,'C':0,'D':0,'E':0,'error':0,'pri':0}
for line in sys.stdin:
    a = line.split('~')
    head  = a[0].split('.')[0]
    # 剔除特殊ip
    if head != '0' and head != '127':
        ip_list.append(a[0])
        mask_list.append(a[1])
ip_correct = []  # 初始化正确的ip位置列表
ip_error = []
mask_correct = []
mask_error = []
for i in range(len(ip_list)):
    # ip判别
    empty_flage = False
    ip_errror_flage = False
    ip = ip_list[i]
    ip_temp = ip.split('.')
    for part in ip_temp:
        if len(part)<1:
            empty_flage = True
    if empty_flage:
        ip_error.append(i)
        continue
    ip_correct.append((i,int(ip_temp[0])))         # 保存争取的索引以及正确ip的类别
for j in range(len(mask_list)):
    # mask判别
    cat_=''
    cat_bin=''
    illage_num=0
    mask_error_flage = False
    mask_empty_flage = False
    mask = mask_list[j]
    mask_temp = mask.split('.')
    for part in mask_temp:
        if len(part)<1:
            mask_empty_flage = True
    if mask_empty_flage:
        mask_error.append(j)
        continue
    for i in range(len(mask_temp)):
        cat_ += bin(int(mask_temp[i]))[2:].zfill(8)
    if cat_.count('1') == len(cat_):
        mask_error.append(j)
        continue
    elif cat_.count('0') == len(cat_):
        mask_error.append(j)
        continue
    bin_mask = []
    for k in range(len(mask_temp)):
        bin_mask.append(bin(int(mask_temp[k]))) # 二进制mask
    for item in bin_mask:
        cat_bin += item[2:].zfill(8)
    # print(cat_bin)
    illage_num+=cat_bin.count('01')
    illage_num+=cat_bin.count('10')
    if illage_num >=2:
        mask_error_flage = True
        mask_error.append(j)
    if mask_empty_flage or mask_error_flage:
        continue
    mask_correct.append(j)          # 仅保存正确掩码的索引
# 计算类别正确类别
for item in ip_correct:
    index,type_ = item
    if index in mask_correct:
        if type_ <128 :
            if type_ == 10 :
                total_num['A'] += 1
                total_num['pri'] += 1
            else:
                total_num['A'] += 1
        elif type_ <192 :
            if type_ == 172 and 15<int(ip_list[index].split('.')[1]) <32:
                total_num['B'] += 1
                total_num['pri'] += 1
            else:
                total_num['B'] += 1
        elif type_ <224 :
            if type_ == 192 and ip_list[index].split('.')[1] == '168':
                total_num['C'] += 1
                total_num['pri'] += 1
            else:
                total_num['C'] += 1
        elif type_ < 240:
            total_num['D'] += 1
        elif type_ <255:
            total_num['E'] += 1
ip_error = list(set(ip_error))
mask_error = list(set(mask_error))
for ip_error_index in ip_error:
    if ip_error_index in mask_error:
        mask_error.remove(ip_error_index)
error_list = ip_error + mask_error
total_num['error'] = len(error_list)
print(total_num['A'],total_num['B'],total_num['C'],total_num['D'],total_num['E'],total_num['error'],total_num['pri'])
发表于 2025-04-03 12:16:10 回复(0)
import sys
#设置变量
num=[0]*7
ips=[]
masks=[]
#存储输入IP地址
for line in sys.stdin:
    address=line.strip().split('~')
    ips.append(address[0])
    masks.append(address[1])

#判断子网掩码是否合法
def ifmask(ipmask):
    if  not ifip(ipmask):
        return False
    bitmask=''.join(bin(int(num))[2:].rjust(8,'0') for num in ipmask)
    if bitmask in ('0'*32,'1'*32):
        return False
    if '1' in bitmask.lstrip('1'):
        return False
    return True

#判断IP地址是否合法
def ifip(ip):
    if len(ip)!=4:
        return False
    for i in ip:
        if not i:
            return False
        if int(i) not in range(0,256):
            return False
    return True

i=0
for a in masks:
    mask=a.split('.')
    ip=ips[i].split('.')
    if int(ip[0])!=(0 or 127):
        if ifmask(mask):
            if ifip(ip):
                if int(ip[0]) in range(1,127):
                    num[0]+=1
                    if int(ip[0])==10:
                        num[6]+=1
                elif int(ip[0]) in range(128,192):
                    num[1]+=1
                    if int(ip[0])==172 and int(ip[1]) in range(16,32):
                        num[6]+=1
                elif int(ip[0]) in range(192,224):
                    num[2]+=1
                    if int(ip[0])==192 and int(ip[1])==168:
                        num[6]+=1
                elif int(ip[0]) in range(224,240):
                    num[3]+=1
                elif int(ip[0]) in range(240,256):
                    num[4]+=1
            else:
                num[5]+=1
        else:
            num[5]+=1
    i+=1

for i in num:
    print(i,end=' ')
发表于 2025-03-27 18:42:24 回复(0)
def is_valid_ip(ip_str):
    parts = ip_str.split(".")
    if len(parts) != 4:
        return False
    for part in parts:
        if not part.isdigit():
            return False
        num = int(part)
        if num < 0 or num > 255:
            return False
    return True

def is_valid_mask(mask_str):
    if not is_valid_ip(mask_str):
        return False
    parts = list(map(int, mask_str.split(".")))
    binary_str = "".join(f"{p:08b}" for p in parts)
    if all(c == "0" for c in binary_str) or all(c == "1" for c in binary_str):
        return False
    first_zero = binary_str.find("0")
    if first_zero == -1:
        return False
    if "1" in binary_str[first_zero:]:
        return False
    return True

error = 0
private = 0
a = 0
b = 0
c = 0
d = 0
e = 0

inf = []
while True:
    try:
        line = input().strip()
        if not line:
            break
        inf.append(line)
    except EOFError:
        break

for line in inf:
    try:
        if "~" not in line:
            error += 1
            continue
        ip_str, mask_str = line.split("~", 1)
        valid_ip = is_valid_ip(ip_str)
        valid_mask = is_valid_mask(mask_str)
        if not (valid_ip and valid_mask):
            error += 1
            continue
        ip_parts = list(map(int, ip_str.split(".")))
        first = ip_parts[0]
        # Check private IP
        is_private = False
        if ip_parts[0] == 10:
            is_private = True
        elif ip_parts[0] == 172 and 16 <= ip_parts[1] <= 31:
            is_private = True
        elif ip_parts[0] == 192 and ip_parts[1] == 168:
            is_private = True
        if is_private:
            private += 1
        # Skip 0.x.x.x and 127.x.x.x
        if first == 0 or first == 127:
            continue
        # Classify
        if 1 <= first <= 126:
            a += 1
        elif 128 <= first <= 191:
            b += 1
        elif 192 <= first <= 223:
            c += 1
        elif 224 <= first <= 239:
            d += 1
        elif 240 <= first <= 255:
            e += 1
    except Exception as ex:  # 修改变量名为ex避免冲突
        error += 1
        # print(f"处理行 {line} 时出错: {ex}")  # 可选的错误打印
print(f"{a} {b} {c} {d} {e} {error} {private}")
发表于 2025-03-19 21:34:01 回复(1)
import sys
li=[0,0,0,0,0,0,0]
def ip5(ips):
    if 1<=ips[0]<=126:
        li[0]+=1
    elif 128<=ips[0]<=191:
        li[1]+=1
    elif 192<=ips[0]<=223:
        li[2]+=1
    elif 224<=ips[0]<=239:
        li[3]+=1
    elif 240<=ips[0]<=255:
        li[4]+=1
    return
def ipsy(ips):
    if ips[0]==10 or ips[0]==172 and 16<=ips[1]<=31 or ips[0]==192 and ips[1]==168:
        li[6]+=1
    return
def ymhf(yms):
    binyms=''
    for i in yms:
        binyms+=bin(i)[2:].rjust(8,'0')
    pos0=binyms.find('0')
    pos1=binyms.rfind('1')
    if pos0!=-1 and pos1!=-1 and pos0-pos1==1:
        return True
    else:
        return False
def judge(line):
    ip,ym=line.split('~')
    ips=[int(i) for i in filter(None,ip.split('.'))]
    yms=[int(i) for i in filter(None,ym.split('.'))]
    if ips[0]==0 or ips[0]==127:
        return
    if len(ips) < 4 or len(yms) < 4:
        li[5] += 1
        return
    if ymhf(yms):
        ip5(ips)
        ipsy(ips)
        return
    else:
        li[5]+=1
        return
for line in sys.stdin:
    judge(line)
for i in li:
    print(i,end=' ')
发表于 2025-03-06 19:13:00 回复(0)
说实话这题目的需求都没有讲清, 写不出来很正常, 需求都是对着不通过的测试集才理清的
import sys


def judge_ip(ip_address: str):
    try:
        num_list = [int(item) for item in ip_address.split(".")]
    except:
        return ['invalid', ' ', ' ']
    num1 = num_list[0]
    num2 = num_list[1]
    num3 = num_list[2]
    num4 = num_list[3]
    if  1<= num1 <= 126:
        if  num1 == 10:
            return ['valid', 'A', 'P']
        else:
            return ['valid', 'A', ' ']
    elif 128<= num1 <= 191:
        if num1 == 172 and 16 <= num2 <= 31:
            return ['valid', 'B', 'P']
        else:
            return ['valid', 'B', ' ']
    elif 192<= num1 <= 223:
        if num1 == 192 and num2 == 168:
            return ['valid', 'C', 'P']
        else:
            return ['valid', 'C', ' ']
    elif 224<= num1 <= 239:
        return ['valid', 'D', ' ']
    elif 240<= num1 <= 255:
        return ['valid', 'E', ' ']
    else:
        return ['pass', ' ', ' ']


def judge_mark(ip_address: str):
    num_list = [bin(int(item))[2:] for item in ip_address.split(".")]
    for i in range(0,4):
        if len(num_list[i]) <8:
            num_list[i] = '0'*(8-len(num_list[i])) + num_list[i]
            
    num_str = ''.join(num_list)
    if num_str.lower() == '1'*32:
        return 'invalid'
    if num_str.lower() == '0'*32:
        return 'invalid'
    for i in range(0, len(num_str)):
        if not num_str[i] == '1':
            for j in range(i, len(num_str)):
                if num_str[j] != '0':
                    return 'invalid'
    return 'valid'

res_dict = {'A':0, 'B':0, 'C':0, 'D':0, 'E':0, 'invalid':0,'P':0}
for item in sys.stdin.readlines():
        if item == '\n':
            continue
        item = item.rstrip('\n')
        slist = item.split('~')
        temp = judge_ip(slist[0])
        temp_mark = judge_mark(slist[1])
        if temp[0] == 'pass':
            continue
        if temp[0] == 'invalid'&nbs***bsp;temp_mark == 'invalid':
            res_dict['invalid'] += 1
            continue
        if temp[1] in res_dict.keys():
            res_dict[temp[1]] += 1
        if temp[2] in res_dict.keys():
            res_dict[temp[2]] += 1
        
        

print(f"{res_dict['A']} {res_dict['B']} {res_dict['C']} {res_dict['D']} {res_dict['E']} {res_dict['invalid'] } {res_dict['P']}")

发表于 2025-02-27 01:20:25 回复(0)