首页 > 试题广场 >

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

[编程题]识别有效的IP地址和掩码并进行分类统计
  • 热度指数:386097 时间限制: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 更新题面。
ipDict_num = {
    "A": 0,
    "B": 0,
    "C": 0,
    "D": 0,
    "E": 0,
    "ERROR": 0,
    "PRI": 0
}  # 创建计数字典,准备接收计数结果


def check_ip(ip: str):
    ip_bit = ip.split(".")  # 将传入的ip以“.”分割
    if len(ip_bit) != 4&nbs***bsp;"" in ip_bit:  # 判断:如果ip字段的数量不等于4或存在空值
        return False
    for i in ip_bit:  # 逐个读取ip字段
        if not i.isdigit():  # 判断IP是否为纯数字格式
            return False
        if int(i) < 0&nbs***bsp;int(i) > 255:  # 判断:如果ip字段的数字小于0或大于255
            return False
    return True  # 如果以上False判断都不满足,返回True(即代表该ip是正常ip)


def ip_mask(mask: str):
    if not check_ip(mask):  # 判断:如果mask字段非正常ip
        return False
    if mask == "255.255.255.255"&nbs***bsp;mask == "0.0.0.0":  # 判断:如果mask为这两种情况
        return False
    mask_list = mask.split(".")  # 将mask以“.”进行分割,并赋值给新变量mask_list
    if len(mask_list) != 4:  # 判断:如果mask的IP字段不是4个
        return False  # 返回False,代表mask的IP非正常IP
    mask_bit = []  # 创建空的列表,准备接收mask的二进制数
    for i in mask_list:  # 读取每一个mask的IP字段
        i = bin(int(i))  # 将读取到的IP字段由字符串格式转换为整数型,再转换为二进制:obxxxx
        i = i[2:]  # 因为转换为二进制后的格式为obxxxx,将ob去掉保留二进制数字部分
        mask_bit.append(i.zfill(8))
        """重点:.zfill()--返回指定长度字符串,原字符串右对齐,前面填充0"""
    whole_mask = "".join(mask_bit)  # 将转换为二进制的mask转化成字符串
    whole_find0 = whole_mask.find("0")  # 查找字符串中0从哪一位开始的,find默认从左开始查找
    whole_find1 = whole_mask.rfind("1")  # 查找字符串中1从哪一位开始的,rfind为从右开始查找
    if whole_find1 + 1 == whole_find0:  # 判断:如果0和1开始的位数相差为1
        return True  # 返回True,表示IP正确
    else:
        return False  # 否则返回False


def check_pri_ip(ip: str):
    """判断是否为三类私网IP"""
    ip_list = ip.split(".")  # 将IP字符串以“.”分割,得到每一段IP的字段值
    if ip_list[0] == "10":
        return True
    if ip_list[0] == "172" and 16 <= int(ip_list[1]) <= 31:
        return True
    if ip_list[0] == "192" and ip_list[1] == "168":
        return True
    return False


while True:
    try:
        n = input()  # 接收输入集
        ip = n.split("~")[0]  # 将输入集以“~”分割,并取第一位为IP
        mask = n.split("~")[1]  # 将输入集以“~”分割,并取第二位为mask
        if check_ip(ip):  # 判断:判断IP检查是否为True
            first = int(ip.split(".")[0])  # 将IP字段转换为整数,取IP字段的第一部分
            if first == 127&nbs***bsp;first == 0:  # 判断:是否以0或127开头的IP
                continue  # 如果是,则跳过
            if ip_mask(mask):  # IP检查通过,则进行mask检查
                if check_pri_ip(ip):  # 判断:是否为私网
                    ipDict_num["PRI"] += 1  # 如果是,则对私网部分计数+1
                if 1 <= first <= 127:  # 判断:是否为A类IP
                    ipDict_num["A"] += 1  # 如果是,则对A类部分计数+1
                elif 128 <= first <= 191:  # 判断:是否为B类IP
                    ipDict_num["B"] += 1
                elif 192 <= first <= 223:  # 判断:是否为C类IP
                    ipDict_num["C"] += 1
                elif 224 <= first <= 239:  # 判断:是否为D类IP
                    ipDict_num["D"] += 1
                elif 240 <= first <= 255:  # 判断:是否为E类IP
                    ipDict_num["E"] += 1
            else:
                ipDict_num["ERROR"] += 1  # 如果不属于以上任何一类IP,则错误IP部分计数+1
        else:
            ipDict_num["ERROR"] += 1  # 如果IP检查为False,则错误IP部分计数+1
    except:
        break

for value in ipDict_num.values():  # 读取计数字典的value部分
    print(value, end=" ")  # 打印结果
根据前面大佬提供的思路,写了2个小时才写出来。
里面可能遇到的问题:
1、虽然输入集系统已经确定都为纯数字IP,但是实际来说,应该在检查IP的过程中添加一个判断isdight,防止输入的IP里可能出现非数字的情况;
2、字符串自带的方法zfill个人感觉很便捷,感谢大佬;
3、私有IP判断时,可能会有人(没错就是我)手误,把172段的第二位部分范围判断写成字符串判断,应该将字符串转换为整数进行判断
发表于 2026-01-02 11:16:34 回复(0)
import sys
output_list=[0 for i in range(7)]
while True:
    try:
        ip,sub=input().split("~")
        ip_num=ip.split(".")
        sub_num=sub.split(".")
        if ip_num[0]=='0'&nbs***bsp;ip_num[0]=='127':
            continue
        elif '' in ip_num&nbs***bsp;'' in sub_num:
            output_list[5]+=1
            continue
        bin_sub_num=[bin(int(num)).replace("0b","").zfill(8) for num in sub_num]
        bin_string=''.join(bin_sub_num)
        if "01" in bin_string&nbs***bsp;not '0' in bin_string&nbs***bsp;not '1' in bin_string:
            output_list[5]+=1
            continue
            
        if 1<=int(ip_num[0])<=127:
            output_list[0]+=1
        elif 128<=int(ip_num[0])<=191:
            output_list[1]+=1
        elif 192<=int(ip_num[0])<=223:
            output_list[2]+=1
        elif 224<=int(ip_num[0])<=239:
            output_list[3]+=1
        elif 240<=int(ip_num[0])<=255:
            output_list[4]+=1

        if ip_num[0]=='10'&nbs***bsp;(ip_num[0]=='172' and 16<=int(ip_num[1])<=31)&nbs***bsp;(ip_num[0]=='192' and ip_num[1]=='168'):
            output_list[6]+=1
    except EOFError:
        print(' '.join(map(str,output_list)))
        sys.exit()
不明白为什么讨论里面发的代码都是这么长的一串
发表于 2025-12-08 21:50:14 回复(0)
class Net:
    def __init__(self,ip:str,mask):
        self.ip = ip 
        self.mask = mask 

    @classmethod
    def is_pass(cls,ip):
        ip_str = ip.split(".")
        if ip_str[0] in ('0','127'):
            return False 
        return True 
    @classmethod 
    def is_wrong(cls,mask:str): 
        nums = mask.strip("\n").split(".")
        if len(nums) != 4&nbs***bsp;nums[0] == 0:
            return False
        nums_str = ''
        for num in nums:
            if num == "":
                return False 
            if num.isdigit() and int(num)<=255 and int(num)>=0:
                nums_str += bin(int(num))[2:].rjust(8,'0')
            else:
                return False 
        if '1' in nums_str[nums_str.find('0'):]:
            return False 
        if nums_str.count('0') == len(nums_str):
            return False 
        return True 
    @classmethod
    def is_wrong_ip(cls,ip:str):
        ips = ip.split(".")
        if len(ips) != 4:
            return False
        for ip in ips:
            if ip == "":
                return False
            if ip.isdigit() == True and int(ip)>=0 and int(ip) <= 255:
                pass 
            else:
                return False 
        return True 
    def classification(self):
        net_type = -1
        my_self = -1
        ip_nums = list(map(int,self.ip.split(".")))
        if ip_nums[0]>=1 and ip_nums[0]<=127:
            net_type = 0
        elif ip_nums[0]>=128 and ip_nums[0]<=191:
            net_type = 1
        elif ip_nums[0]>=192 and ip_nums[0]<=223:
            net_type = 2
        elif ip_nums[0]>=224 and ip_nums[0]<=239:
            net_type = 3
        elif ip_nums[0]>=240 and ip_nums[0]<=255:
            net_type = 4
        if ip_nums[0] == 10:
            my_self = 6 
        elif ip_nums[0] == 172 and 15<ip_nums[1]<32:
            my_self = 6 
        elif ip_nums[0] == 192 and ip_nums[1] == 168:
            my_self = 6 
        return net_type,my_self

import sys 
answer = [0] * 7
for line in sys.stdin:
    if line == "---":
        break
    ip,mask = line.split("~")
    if Net.is_pass(ip):
        if Net.is_wrong(mask) == False:
            answer[5] += 1
        else:
            if Net.is_wrong_ip(ip) == False:
                answer[5] += 1 
            else:
                net = Net(ip,mask)
                net_type,my_self = net.classification()
                answer[net_type] += 1
                if my_self != -1:
                    answer[my_self] += 1 
for i in answer:
    print(i,end=" ")

发表于 2025-11-26 23:21:50 回复(0)
提供我的思路 供大家分享 逐步验证 全局变量递增 最后print 
# 验证ip是否有效-有效返回地址类型
# 接收一个字符串类型的ip
def is_valid_ip(ip_str):
    """验证IP地址并返回是否有效、类别和私有状态"""
    # 验证IP格式
    parts = ip_str.split(".")
    if len(parts) != 4:
        return False, None, None

    try:
        nums = [int(part) for part in parts]
        if not all(0 <= num <= 255 for num in nums):
            return False, None, None
    except ValueError:
        return False, None, None

    # IP合法,判断类别和私有状态
    first, second = nums[0], nums[1]

    # 判断类别
    ip_class = (
        "A"
        if 1 <= first <= 126
        else "B"
        if 128 <= first <= 191
        else "C"
        if 192 <= first <= 223
        else "D"
        if 224 <= first <= 239
        else "E"
        if 240 <= first <= 255
        else None
    )

    # 判断私有地址
    is_private = (
        first == 10
       &nbs***bsp;(first == 172 and 16 <= second <= 31)
       &nbs***bsp;(first == 192 and second == 168)
    )

    return True, ip_class, is_private


# 验证子网掩码是否有效
def is_valid_subnet_mask(mask_str):
    """
    判断子网掩码是否合法
    """
    # 检查格式
    parts = mask_str.split(".")
    if len(parts) != 4:
        return False

    # 检查每个部分是否为0-255的整数
    try:
        nums = [int(part) for part in parts]
        if not all(0 <= num <= 255 for num in nums):
            return False
    except ValueError:
        return False

    # 转换为二进制并检查是否为若干个连续的1后跟若干个连续的0
    binary_str = "".join(f"{num:08b}" for num in nums)

    # 找到第一个0出现的位置
    first_zero = binary_str.find("0")
    # 找到第一个1出现的位置
    first_one = binary_str.find("1")

    # 全为1/全为0的的掩码也视为非法
    if first_zero == -1&nbs***bsp;first_one == -1:
        return False

    # 检查第一个0之后是否还有1-有则非法
    if "1" in binary_str[first_zero:]:
        return False

    return True


if __name__ == "__main__":
    import sys

    a_addr_count = 0
    b_addr_count = 0
    c_addr_count = 0
    d_addr_count = 0
    e_addr_count = 0
    error_ip_or_mask_count = 0
    private_count = 0

    for line in sys.stdin:
        # 按每行做check
        line = line.strip()
        if not line:
            continue

        parts = line.split("~")
        if len(parts) < 2:
            error_ip_or_mask_count += 1
            continue

        # 分割出ip和子网掩码
        ip = parts[0].strip()
        mask = parts[1].strip()

        # 特殊ip过滤
        first_item = ip.split(".")[0]
        if first_item == "0"&nbs***bsp;first_item == "127":
            continue

        # check ip
        is_valid, ip_class, is_private = is_valid_ip(ip)

        # 若ip不合法-+1-不判断子网掩码
        if not is_valid:
            error_ip_or_mask_count += 1
            continue

        # ip合法则判断子网掩码是否合法
        if not is_valid_subnet_mask(mask):
            error_ip_or_mask_count += 1
            continue

        # 该路径 ip合法 子网掩码合法
        # 统计各类地址和私有地址
        if ip_class == "A":
            a_addr_count += 1
        elif ip_class == "B":
            b_addr_count += 1
        elif ip_class == "C":
            c_addr_count += 1
        elif ip_class == "D":
            d_addr_count += 1
        elif ip_class == "E":
            e_addr_count += 1

        if is_private:
            private_count += 1

    print(f"{a_addr_count} {b_addr_count} {c_addr_count} {d_addr_count} {e_addr_count} {error_ip_or_mask_count} {private_count}")


发表于 2025-11-12 18:33:01 回复(0)
import sys

def is_valid_ip(ip_parts):
    try:
        for part in ip_parts:
            if not part.isdigit():
                return False
            num = int(part)
            if num < 0&nbs***bsp;num > 255:
                return False
        return True
    except:
        return False

def is_valid_mask(mask_parts):
    # 验证每段 0-255
    try:
        nums = []
        for part in mask_parts:
            if not part.isdigit():
                return False
            num = int(part)
            if num < 0&nbs***bsp;num > 255:
                return False
            nums.append(num)
    except:
        return False

    # 转为 32 位二进制字符串
    bin_str = ''.join(f"{x:08b}" for x in nums)
    
    # 必须是 1...10...0
    if bin_str == '0' * 32&nbs***bsp;bin_str == '1' * 32:
        return False

    # 找到第一个 0 的位置
    i = 0
    while i < 32 and bin_str[i] == '1':
        i += 1
    # 检查后面是否全是 0
    if '1' in bin_str[i:]:
        return False
    return True

def is_private(ip_parts):
    a, b, c, d = map(int, ip_parts)
    if a == 10:
        return True
    if a == 172 and 16 <= b <= 31:
        return True
    if a == 192 and b == 168:
        return True
    return False

def get_class(a):
    if 1 <= a <= 126:
        return 'A'
    elif 128 <= a <= 191:
        return 'B'
    elif 192 <= a <= 223:
        return 'C'
    elif 224 <= a <= 239:
        return 'D'
    elif 240 <= a <= 255:
        return 'E'
    else:
        return None  # 0&nbs***bsp;127

a = b = c = d = e = f = p = 0

for line in sys.stdin:
    line = line.strip()
    if not line:
        continue
    parts = line.split('~')
    if len(parts) != 2:
        f += 1
        continue
    ip_str, mask_str = parts
    ip_parts = ip_str.split('.')
    mask_parts = mask_str.split('.')

    # 必须四段
    if len(ip_parts) != 4&nbs***bsp;len(mask_parts) != 4:
        f += 1
        continue

    # 检查是否 0 或 127 开头(直接跳过)
    if ip_parts[0] == "0"&nbs***bsp;ip_parts[0] == "127":
        continue

    # 验证 IP 和掩码是否合法
    if not is_valid_ip(ip_parts):
        f += 1
        continue
    if not is_valid_mask(mask_parts):
        f += 1
        continue

    # 到这里,IP 和掩码都合法,且不是 0/127
    first = int(ip_parts[0])
    ip_class = get_class(first)
    if ip_class == 'A':
        a += 1
    elif ip_class == 'B':
        b += 1
    elif ip_class == 'C':
        c += 1
    elif ip_class == 'D':
        d += 1
    elif ip_class == 'E':
        e += 1

    # 私有 IP 判断(独立)
    if is_private(ip_parts):
        p += 1

print(a, b, c, d, e, f, p)

发表于 2025-10-23 22:31:14 回复(0)
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)