首页 > 试题广场 >

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

[编程题]识别有效的IP地址和掩码并进行分类统计
  • 热度指数:322242 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。

所有的IP地址划分为 A,B,C,D,E五类

A类地址从1.0.0.0到126.255.255.255;

B类地址从128.0.0.0到191.255.255.255;

C类地址从192.0.0.0到223.255.255.255;

D类地址从224.0.0.0239.255.255.255;

E类地址从240.0.0.0255.255.255.255


私网IP范围是:

从10.0.0.0到10.255.255.255

从172.16.0.0到172.31.255.255

从192.168.0.0到192.168.255.255


子网掩码为二进制下前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
(注意二进制下全是1或者全是0均为非法子网掩码)

注意:
1. 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略
2. 私有IP地址和A,B,C,D,E类地址是不冲突的



输入描述:

多行字符串。每行一个IP地址和掩码,用~隔开。

请参考帖子https://www.nowcoder.com/discuss/276处理循环输入的问题。


输出描述:

统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。

示例1

输入

10.70.44.68~255.254.255.0
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

说明

10.70.44.68~255.254.255.0的子网掩码非法,19..0.~255.255.255.0的IP地址非法,所以错误IP地址或错误掩码的计数为2;
1.0.0.1~255.0.0.0是无误的A类地址;
192.168.0.2~255.255.255.0是无误的C类地址且是私有IP;
所以最终的结果为1 0 1 0 0 2 1        
示例2

输入

0.201.56.50~255.255.111.255
127.201.56.50~255.255.111.255

输出

0 0 0 0 0 0 0

说明

类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略         
python最低端的写法
import sys
A=0
B=0
C=0
D=0
E=0
count=0
siyo=0
def congzu(a,x):
    k=''
    h=[]
    if a[-1]!=x:
        a=a+x
        for i in a:
            if i!=x:
                k=k+str(i)
            else:
                h.append(k)
                k=''
    else:
        for i in a:
            if i != x:
                k=k+str(i)
            else:
                h.append(k)
                k=''
    return h
apt=[]
try:
    while True:
        line=sys.stdin.readline().strip()
        if line=='':
            break
        apt.append(line)
except:
    pass
for v in apt:
    Ide=v.index('~')
    IP=v[:Ide]
    IPY=v[Ide+1:]
    ym=list(filter(None,congzu(IPY,'.')))
    if len(ym)==4 and ym!=['255','255','255','255'] and ym!=['0','0','0','0']:
        t=1
        for y in ym:
            if int(y)>=0 and int(y)<256:
                for x in ('{:08b}'.format(int(y))):
                    if t-int(x)>=0:
                        t=int(x)
                        yero=True
                    else:
                        count=count+1
                        yero=False
                        break
                if yero==False:
                    break
        if yero == False:
            pass
        else:
            ip=list(filter(None,congzu(IP,'.')))
            if ip[0]!='0':
                if len(ip)==4:
                    for i in ip:
                        try:
                            int(i)
                            if int(i)>=0 and int(i)<256:
                                iero=True
                            else:
                                iero=False
                                count = count + 1
                                break
                        except:
                            iero=False
                            count=count+1
                            break
                    if iero==False:
                        break
                    else:
                        if int(ip[0]) in range(1,127):
                            A=A+1
                            if int(ip[0])==10:
                                siyo=siyo+1
                        elif int(ip[0]) in range(128,192):
                            B=B+1
                            if int(ip[0])==172 and int(ip[1])in range(16,32):
                                siyo=siyo+1
                        elif int(ip[0]) in range(192,224):
                            C=C+1
                            if int(ip[0]) == 192 and int(ip[1])==168:
                                siyo=siyo+1
                        elif int(ip[0]) in range(224,240):
                            D=D+1
                        elif int(ip[0]) in range(240,255):
                            E=E+1
                        else:
                            pass
                else:
                    count=count+1
            else:
                pass
    else:
        count=count+1
print str(A)+' '+str(B)+' '+str(C)+' '+str(D)+' '+str(E)+' '+str(count)+' '+str(siyo)


编辑于 2019-10-11 15:43:08 回复(3)
// 注意:0.0.0.0~0.255.255.255 不属于任何一类,不属于错误一类。 #include <iostream>
#include <string>
#include <vector>
using namespace std;
int p[7]={0};
void is(string s){
    int a=0,b=0,flag;
	vector<int> vec(4);
    for(int i=0;i<s.length();i++){
        a=0;
        flag=0;
        for(;i<s.length()&&s[i]!='.';i++){
            flag=1;
            if(s[i]>='0'&&s[i]<='9')
            	a=a*10+s[i]-'0';
            else{
            	p[5]++;
                return;
            }
        }
     	if(flag&&a<256)
            vec[b]=a;
        else{
            p[5]++;
            return;
        }
        b++;
    }
    if(vec[0]>0){
    	if(vec[0]<127){
			p[0]++;
            if(vec[0]==10)
                p[6]++;
        }else if(vec[0]<192&&vec[0]>127){
			p[1]++;
            if(vec[0]==172&&vec[1]>=16&&vec[1]<=31)
                p[6]++;
        }else if(vec[0]>191&&vec[0]<224){
			p[2]++;
            if(vec[0]==192&&vec[1]==168)
                p[6]++;
        }else if(vec[0]>223&&vec[0]<240)
            p[3]++;
        else if(vec[0]>239)
            p[4]++;
    }
}
int isvalid(string s){
	int a,b=0,flag,flag2=0;
    vector<int> vec(4);
	for(int i=0;i<s.length();i++){
		a=0;flag=0;
		for(;i<s.length()&&s[i]!='.';i++){
            flag=1;
            if(s[i]>='0'&&s[i]<='9')
            	a=a*10+s[i]-'0';
            else
            	return 0;
        }
        if(flag&&(a==255||a==254||a==252||a==248||a==240||a==224||a==192||a==128||a==0))
            vec[b]=a;
        else 
            return 0;
        b++;
	}
    for(int i=0;i<4;i++){
        if(flag2==0){
            if(vec[i]<255)
                flag2=1;
        }else{
            if(vec[i]!=0)
                return 0;   
        }
    }
    if(vec[3]==255)
        return 0;
    return 1; 
}
int main(){
    string s;
    int i;
    while(cin>>s){
        string ss,sss;
        for(i=0;i<s.length()&&s[i]!='~';i++);
        ss=s.substr(0,i);  
		sss=s.substr(i+1,s.length()-i);
		if(isvalid(sss))
			is(ss);
		else
			p[5]++;        
    }
    cout<<p[0]<<" "<<p[1]<<" "<<p[2]<<" "<<p[3]<<" "<<p[4]<<" "<<p[5]<<" "<<p[6]<<endl;
    return 0;
}

编辑于 2016-08-29 23:16:38 回复(2)
import sys

def ignore(ip):
    if (ip[0] == '0'&nbs***bsp;ip[0] == '127') and ip[1] and ip[2] and ip[3]:
        return True
    return False    

def isip(ip):
    for i in ip:
        if  not 0<=int(i)<=255: return False
    return True    

def ismask(mask):
    mask = map(int,mask)
    maskstr = ''
    for m in mask:
        if not (m == 0&nbs***bsp;126 < m < 256):
            return False
        bin_m = '0'*8 if m==0 else bin(m)[2:]
        maskstr = maskstr + bin_m
#     print(maskstr)
    i,j = 0,31
    while maskstr[i]=='1' and i < 32: i+=1
    while maskstr[j]=='0' and j > -1: j-=1
    if i==32&nbs***bsp;j == -1&nbs***bsp;i-j!=1:
#         print(i,j)
        return False
    return True

a,b,c,d,e,err,pr = 0,0,0,0,0,0,0

for line in sys.stdin:
    ip, mask = line.strip().split('~')
    ip = ip.split('.')
    mask = mask.split('.')
#     print(ip,mask)
    if ignore(ip): continue
    try:
        if not isip(ip)&nbs***bsp;not ismask(mask):
            err += 1
            continue
    except:
        err += 1
        continue
    ip = list(map(int,ip))
    if 1 <= ip[0] <= 126: 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
    
    if ip[0]==10&nbs***bsp;(ip[0]==172 and 16<=ip[1]<=31)&nbs***bsp;(ip[0]==192 and ip[1]==168):
        pr += 1
print(a,b,c,d,e,err,pr)

发表于 2022-07-09 17:34:34 回复(0)
#include<bits/stdc++.h>
using namespace std;
int a=0,b=0,c=0,d=0,e=0,error_data=0,private_data=0;
bool valid_mask(string mask){
    bool ret = 1;
    int one_num = 0;
    vector<int> int_data;
    
    int left = 0;
    for(int index = 0 ; index < mask.size() ; index++){//将string类型的地址转换为int型
        string temp;
        
        if(index == mask.size() - 1){
            temp = mask.substr(left,index-left+1);
            int_data.push_back(stoi(temp));
        }
        
        if(mask[index] == '.'){
            temp = mask.substr(left,index-left);
            int_data.push_back(stoi(temp));
        }else{
            continue;
        }
        

        left = index + 1;
    }
    
    //如果按照正常的掩码规则,根据1最后出现位置,推理应该有多少个1
    int j;
    for(j = int_data.size() - 1 ; j >= 0 ; j--){
        int cur = int_data[j];
        
        if(cur&0x1 == 1){
            one_num = 8;
            break;
        }else
        {
            int flag = 0;
            for(int s = 0 ; s < 7 ; s++){
                cur = cur >> 1;
                if(cur&0x1 == 1){
                    one_num = 7-s;
                    flag = 1;
                    break;
                }
            } 
            
            if(flag == 1)
                break;
        }
        
          
    }
    one_num = one_num + j*8;//推理出的1的个数
    if(one_num == 32 || one_num == 0)
        return false;
    
    
    int count = 0;
    for(int index = 0 ; index < int_data.size() ; index++){//计算掩码中实际1出现的次数
        int temp = int_data[index];
        while(temp){
            count += temp&0x1;
            temp = temp >> 1;
        }
    }
    
    ret = count==one_num? true:false;//若干推理的次数和实际计算相等则掩码正确,否则掩码不符合要求
    return ret;
}

int ip_net_type(string ip_net,string mask){
    /*
    返回1 表A类地址
    返回2 表B类地址
    返回3 表C类地址
    返回4 表D类地址
    返回5 表E类地址
    
    返回8 计数忽略
    */
    int ret = 8;
    
    vector<int> int_data;
    
    int left = 0;
    for(int index = 0 ; index < ip_net.size() ; index++){//将string类型的地址转换为int型
        string temp;
        
        if(index == ip_net.size() - 1){
            temp = ip_net.substr(left,index-left+1);
            int_data.push_back(stoi(temp));
        }
        
        if(ip_net[index] == '.'){
            temp = ip_net.substr(left,index-left);
            int_data.push_back(stoi(temp));
        }else{
            continue;
        }
        left = index + 1;
    }
    
    
    //判断ip地址属于哪一类型
    if(int_data[0] >= 1 && int_data[0] <= 126){
        if(int_data[0] == 10){//属于私有ip
            if(valid_mask(mask)){//同时掩码符合规则
                private_data++;
            }
        }
        return 1;
        
    }else if(int_data[0] >= 128 && int_data[0] <= 191){
        if(int_data[0] == 172 && int_data[1] >= 16 && int_data[1] <= 31){
            if(valid_mask(mask)){
                private_data++;
            }
        }
        return 2;
        
    }else if(int_data[0] >= 192 && int_data[0] <= 223){
        if(int_data[0] == 192 && int_data[1] == 168){
            if(valid_mask(mask)){
                private_data++;
            }
        }
        return 3;
    }else if(int_data[0] >= 224 && int_data[0] <= 239){
        return 4;
    }else if(int_data[0] >= 240 && int_data[0] <= 255){
        return 5;
    }
    
    
    return ret;
}

bool get_ip_valid(string ip_net){
    int left = 0;
    for(int index = 0 ; index < ip_net.size() ; index++){
        if(index == ip_net.size() - 1 && ip_net[index] == '.'){
            return false;
        }
        
        if(ip_net[index] == '.'){
            if(left == index){
                return false;
            }else{
                left = index+1;
            }
        }
        
        
    }
    return true;
}



int main()
{
    
    string ipdata;
    
    while(getline(cin , ipdata))
    {
        int index = 0;
        int len = ipdata.size();
        
        while(ipdata[index] != '~')
            index++;
        
        string ip_net = ipdata.substr(0,index);//ip地址
        string mask = ipdata.substr(index+1,len-index-1);//子网掩码
        
        if(get_ip_valid(ip_net)){//ip合法
            int ip_type = ip_net_type(ip_net,mask);//ip属于哪一类型
            if(ip_type != 8){//ip属于规定的类型;当返回值为8时,ip属于定义类型以外
                if(valid_mask(mask)){
                    switch(ip_type){
                        case 1:{
                            a++;
                            break;
                        }case 2:{
                            b++;
                            break;
                        }case 3:{
                            c++;
                            break;
                        }case 4:{
                            d++;
                            break;
                        }case 5:{
                            e++;
                            break;
                        }default:break;
                    }
                    
                }else{
                    error_data++;
                }
            }
        }else{
            error_data++;
        }
    }
    cout<< a <<" "<<b<<" "<<c<<" "<<d<<" "<<e<<" "<<error_data<<" "<<private_data<<endl;
    return 0;
}

发表于 2022-07-07 20:49:03 回复(0)
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int[] res = new int[7];
        int typeA = 0;
        int typeB = 1;
        int typeC = 2;
        int typeD = 3;
        int typeE = 4;
        int typeError = 5;
        int typePrivate = 6;
        while (in.hasNext()) {
            String ip_mask = in.nextLine();
            String[] im = ip_mask.split("~");
            String ip = im[0];
            String mask = im[1];
            if (!isValidIp(ip) || !(isValidIp(mask) && isValidMask(mask))) {
                res[typeError]++;
                continue;
            }
            if (isTypeA(ip)) {
                res[typeA]++;
            } else if (isTypeB(ip)) {
                res[typeB]++;
            } else if (isTypeC(ip)) {
                res[typeC]++;
                if (isPrivateIp(ip)) {
                    res[typePrivate]++;
                }
            } else if (isTypeD(ip)) {
                res[typeD]++;
            } else if (isTypeE(ip)) {
                res[typeE]++;
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < res.length; i++) {
            sb.append(res[i]);
            sb.append(" ");
        }
        System.out.println(sb.toString());
    }
    
    public static boolean isValidIp(String s) {
        String[] addrs = getAddrs(s);
        for (int i = 0; i < addrs.length; i++) {
            if (addrs[i].length() <= 0) {
                return false;
            }
        }
        return true;
    }
    // 111100001 出现01则无效
    // 111111110
    // 000000000 不对
    // 111111111 不对
    // 这里也可以枚举可能情况 一共也就14种
    
    public static boolean isValidMask(String s) {
        String[] addrs = getAddrs(s);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < addrs.length; i++) {
//             System.out.println(addrs[i]);
//             Integer.parseInt(addrs[i], 2);
            sb.append(Integer.toBinaryString(Integer.parseInt(addrs[i])));
        }
        String bs = sb.toString();
        if (bs.indexOf("01") >= 0 || bs.indexOf("10") < 0) {
            return false;
        }
        return true;
    }
    
    public static boolean isTypeA(String s) {
        String[] addrs = getAddrs(s);
        int topAddr = Integer.parseInt(addrs[0]);
        if (topAddr >= 1 && topAddr <= 126) {
            return true;
        }
        return false;
    }
    
    public static boolean isTypeB(String s) {
        String[] addrs = getAddrs(s);
        int topAddr = Integer.parseInt(addrs[0]);
        if (topAddr >= 128 && topAddr <= 191) {
            return true;
        }
        return false;
    }
    
    public static boolean isTypeC(String s) {
        String[] addrs = getAddrs(s);
        int topAddr = Integer.parseInt(addrs[0]);
        if (topAddr >= 192 && topAddr <= 223) {
            return true;
        }
        return false;
    }
    
    public static boolean isTypeD(String s) {
        String[] addrs = getAddrs(s);
        int topAddr = Integer.parseInt(addrs[0]);
        if (topAddr >= 224 && topAddr <= 239) {
            return true;
        }
        return false;
    }
    
    public static boolean isTypeE(String s) {
        String[] addrs = getAddrs(s);
        int topAddr = Integer.parseInt(addrs[0]);
        if (topAddr >= 240 && topAddr <= 255) {
            return true;
        }
        return false;
    }
    
    public static boolean isPrivateIp(String s) {
        String[] addrs = getAddrs(s);
        int topAddr = Integer.parseInt(addrs[0]);
        int secondAddr = Integer.parseInt(addrs[1]);
        if (topAddr == 10) {
            return true;
        }
        if (topAddr == 172 && secondAddr >= 16 && secondAddr <= 31) {
            return true;
        }
        if (topAddr == 192 && secondAddr == 168) {
            return true;
        }
        return false;
    }
    
    public static String[] getAddrs(String s) {
        return s.split("\\.");
    }
}
发表于 2022-05-10 10:38:08 回复(0)
l=[]
while True:
    try:
        l.append(input())
    except:
        break
def is_code(x):
    l0=[]
    for i in x:
        tmp=bin(i)
        tmp=tmp[2:]
        l0.append(tmp.zfill(8))
    l0=''.join(l0)
    a=l0.rfind('1')
    b=l0.find('0')
    if l0.startswith('1') and l0.endswith('0') and b-a==1:
        return True
    else:
        return False
        
        
def is_right(x):
    x=x.split('~')
    flag=True
    t=x[0].split('.')
    v=x[1].split('.')
    if '' in t:
        for i in range(t.count('')):
            t.remove('')
    if '' in v:
        for i in range(v.count('')):
            v.remove('')
    ip=[int(i) for i in t]
    net_code=[int(i) for i in v]
    if not (len(ip)==4 and len(net_code)==4):
        flag = False
    for i in ip:
        if not 0<=i<=255:
            flag =False
            break
    for i in net_code:
        if not 0<=i<=255:
            flag =False
            break
    if not is_code(net_code):
        flag = False
    return flag
    
def ip_class(x):
    if 1<=x[0]<=126:
        return 'A'
    elif 128<=x[0]<=191:
        return 'B'
    elif 192<=x[0]<=223:
        return 'C'
    elif 224<=x[0]<=239:
        return 'D'
    elif 240<=x[0]<=255:
        return 'E'
    
def is_private(x):
    if x[0]==10&nbs***bsp;(x[0]==172 and 16<=x[1]<=31)&nbs***bsp;(x[0]==192 and x[1]==168):
        return True
    else:
        return False

l1=[]
l2=[]
n=0
for i in l:
    if not is_right(i):
        n+=1
    else:
        item=i.split(r'~')
        t=item[0].split('.')
        if '' in t:
            for i in range(t.count('')):
                t.remove('')
        ip=[int(i) for i in t]
        l1.append(ip_class(ip))
        l2.append(is_private(ip))
        
print(l1.count('A'),l1.count('B'),l1.count('C'),l1.count('D'),l1.count('E'),n,l2.count(True))

发表于 2021-12-16 20:08:08 回复(0)
// C语言版本。
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

int is_legal_ip(char* ipaddr)
{
    char* tmp_ipaddr = strdup(ipaddr);
    int count = 0;
    char* tmp = strtok(tmp_ipaddr, ".");
    if (!tmp)
        return false;
    // int num = atoi(tmp);
    // if (num == 0 || num == 127)  // 这种IP地址需要忽略
    //    return false;

    while (tmp) {
        count++;
        int num = atoi(tmp);
        if (num < 0 || num >  255)
            return false;
        tmp = strtok(NULL, ".");
    }

    if (count != 4)
        return false;
    return true;
}

bool is_legal_mask(char* mask)
{
    char* tmp_mask = strdup(mask);
    unsigned int num = 0;
    char* tmp = strtok(tmp_mask, ".");
    while (tmp) {
        num = num << 8;
        num += atoi(tmp);
        tmp = strtok(NULL, ".");
    }
    if (!num) // 如果32位无符号整数0,则表示输入的全是0,就是非法的掩码
        return false;
    num = ~num + 1; // 对整数取反 + 1,得到的数如果等于1,则表示输入的全是1,也是非法掩码
    if (num == 1)
        return false;
    if ((num & (num - 1)) != 0) // 类似 0001000 & 0000111 是等于0的,非0,则表示掩码有问题。
        return false;
    return true;
}

bool is_private_ip(char* ipaddr)
{
    char* tmp_ipaddr = strdup(ipaddr);
    char* tmp = strtok(tmp_ipaddr, ".");
    int num1 = atoi(tmp);
    if (num1 != 10 && num1 != 172 && num1 != 192)
        return false;

    tmp = strtok(NULL, ".");
    int num2 = atoi(tmp);
    if (num1 == 172 && (num2 < 16 || num2 > 31))
        return false;
    if (num1 == 192 && (num2 != 168))
        return false;
    return true;
}

int main()
{
    char arr[1000][100] = { 0 };
    int cnt = 0;
    while (scanf("%s", arr[cnt]) != EOF)
        cnt++;

    int a = 0;
    int b = 0;
    int c = 0;
    int d = 0;
    int e = 0;
    int err = 0;
    int pri = 0;

    for (int i = 0; i < cnt; i++) {
        char* ipaddr = strtok(arr[i], "~");
        if (!ipaddr) {
            err++;
            continue;
        }
        char* mask = strtok(NULL, "~");
        if (!mask) {
            err++;
            continue;
        }
        if (!is_legal_ip(ipaddr) || !is_legal_mask(mask)) {
            err++;
            continue;
        }
        if (is_private_ip(ipaddr))
            pri++;

        char* tmp = strtok(ipaddr, ".");
        int num = atoi(tmp);
        if (1 <= num && num <= 126)
            a++;
        else if (128 <= num && num <= 191)
            b++;
        else if (192 <= num && num <= 223)
            c++;
        else if (224 <= num && num <= 239)
            d++;
        else if (240 <= num && num <= 255)
            e++;
        // else // 忽略10 和 127 开头的IP地址。
    }
    printf("%d %d %d %d %d %d %d\n", a, b, c, d, e, err, pri);
    return 0;
}

发表于 2021-08-02 00:59:37 回复(0)
#include <iostream>
#include <vector>
#include <string>
#include <bitset>

using namespace std;
int main()
{
    string str;
    int Anum=0,Bnum=0,Cnum=0,Dnum=0,Enum=0,Ernum=0,Snum=0;
    while(getline(cin,str))
    {
        size_t pos=str.find("~");
        if(pos!=string::npos)
        {
            string a=str.substr(0,pos);
            string b=str.substr(pos+1,str.size()-pos-1);
            vector<string> temp1;
            vector<string> temp2;
            
            size_t pos1=a.find(".");
            while(pos1!=string::npos)
            {
                temp1.push_back(a.substr(0,pos1));
                a=a.substr(pos1+1,a.size()-pos1-1);
                pos1=a.find(".");
            }
            if(!a.empty())
            temp1.push_back(a);
          
            size_t pos2=b.find(".");
            while(pos2!=string::npos)
            {
                temp2.push_back(b.substr(0,pos2));
                b=b.substr(pos2+1,b.size()-pos2-1);
                pos2=b.find(".");
            }
            if(!b.empty())
            temp2.push_back(b);
            
            bool IsNext=true;
            
            if(IsNext)
            {
                string strMask;
                for(int i=0;i<temp2.size();i++)
                {
                    bitset<8> b(stoi(temp2[i]));
                    strMask+=b.to_string();
                }
                size_t pos=strMask.find("01");
                size_t pos1=strMask.find("0");
                size_t pos2=strMask.find("1");
                
                if(pos==string::npos&&!(pos1==string::npos&&pos2!=string::npos)
                   &&!(pos2==string::npos&&pos1!=string::npos))
                {
                    IsNext=true;
                }
                else
                {
                    IsNext=false;
                    Ernum++;
                    continue;
                }
            }
            
            vector<int> t1;
            if(IsNext)
            {
                for(int i=0;i<temp1.size();i++)
                {
                    if(temp1[i].empty())
                    {
                        Ernum++;
                        IsNext=false;
                        break;
                    }
                    else
                    {
                        int value=stoi(temp1[i]);
                        if(i==0&&(value==0||value==127))
                        {
                            IsNext=false;
                            break;
                        }
                        else if(value>255||value<0)
                        {
                            Ernum++;
                            IsNext=false;
                            break;
                        }
                        else
                        {
                            t1.push_back(value);
                        }
                    }
                }
            }
            
            if(IsNext)
            {
                if(t1[0]>=1&&t1[0]<=126)
                {
                    Anum++;
                }
                else if(t1[0]>=128&&t1[0]<=191)
                {
                    Bnum++;
                }
                else if(t1[0]>=192&&t1[0]<=223)
                {
                    Cnum++;
                }
                else if(t1[0]>=224&&t1[0]<=239)
                {
                    Dnum++;
                }
                else if(t1[0]>=240&&t1[0]<=255)
                {
                    Enum++;
                }
                
                if(t1[0]==10)
                {
                    Snum++;
                }
                else if(t1[0]==172&&t1[1]>=16&&t1[1]<=32)
                {
                    Snum++;
                }
                else if(t1[0]==192&&t1[1]==168)
                {
                    Snum++;
                }
            }
        }
    }
    cout<<Anum<<" "<<Bnum<<" "<<Cnum<<" "<<Dnum<<" "<<Enum<<" "<<Ernum<<" "<<Snum;
}

发表于 2021-06-29 03:50:04 回复(0)
修修改改半天才做出来,需要注意的是,不在ABCDE里面的IP地址,不算是错误的地址,掩码错才算错,如果掩码对则忽略这部分IP的计数即可。
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<unordered_set>
#include<set>
using namespace std;

int checkip(string ip,bool& priva) {
    int len=ip.size();
    vector<int> a;
    int pre=0,i;
    for(i=0;i<len;++i) {
        if(ip[i]=='*') {
            return 0; //含有*的,计数时忽略
        }
        if(ip[i]=='.') {
            if(i==pre) {
                //连续的点
                return -1; //错误的IP地址
            }
            int x=atoi(ip.substr(pre,i-pre).c_str());
            pre=i+1;
            if(x>255)
                return -1;
            a.push_back(x);
        } else if(ip[i]<'0' || ip[i]>'9') {
            return -1; //非法字符,错误ip
        }
    }
    if(i==pre) {
        //连续的点
        return -1; //错误的IP地址
    }
    int x=atoi(ip.substr(pre,i-pre).c_str());
    pre=i+1;
    if(x>255)
        return -1;
    a.push_back(x);
    if(a.size()!=4)
        return -1; //错误ip
    if(a[0]>=1 && a[0]<=126) {
        if(a[0]==10)
            priva=true; //私有ip
        return 1;
    }
    if(a[0]>=128 && a[0]<=191) {
        if(a[0]==172 && a[1]>=16 && a[1]<=31)
            priva=true;
        return 2;
    }
    if(a[0]>=192 && a[0]<=223) {
        if(a[0]==192 && a[1]==168)
            priva=true;
        return 3;
    }
    if(a[0]>=224 && a[0]<=239)
        return 4;
    if(a[0]>=240 && a[0]<=255)
        return 5;
    return 0;
}
int checkmask(string mask) {
    //判断子网掩码
    int len=mask.size();
    vector<int> a;
    int pre=0,i;
    for(i=0;i<len;++i) {
        if(mask[i]=='.') {
            if(i==pre) {
                return -1; //错误
            }
            int x=atoi(mask.substr(pre,i-pre).c_str());
            pre=i+1;
            if(x>255)
                return -1;
            a.push_back(x);
        } else if(mask[i]<'0' || mask[i]>'9') {
            return -1; //非法字符
        }
    }
    if(i==pre) {
        return -1; //错误
    }
    int x=atoi(mask.substr(pre,i-pre).c_str());
    pre=i+1;
    if(x>255)
        return -1;
    a.push_back(x);
    if(a.size()!=4)
        return -1; //错误
    int tem=a[0]+a[1]+a[2]+a[3];
    if(tem==0 || tem==255*4)
        return -1; //全0或者全1均为非法
    bool zero=false;
    unordered_set<int> s={128,192,224,240,248,252,254,255};
    for(int i=0;i<4;++i) {
        if(a[i]==0) {
            zero=true;
            continue;
        }
        if(a[i]!=0 && zero==true)
            return -1;
        if(s.count(a[i])==0)
            return -1;
        if(a[i]!=255)
            zero=true;
    }
    return 1;
}
int main()
{
    string str;
    int a=0,b=0,c=0,d=0,e=0;
    int err=0;
    int priv=0;
    while(cin>>str) {
        int i=0;
        for(;i<str.size();++i) {
            if(str[i]=='~')
                break;
        }
        string ip=str.substr(0,i);
        string mask=str.substr(i+1);
        bool isPrivate=false;
        int x=checkip(ip,isPrivate);
        if(x==-1) {
            err++;
            continue;
        }
        int y=checkmask(mask);
        if(y==-1) {
            err++; //错误IP或者掩码
            continue;
        }
        switch(x){
            case 1: a++; break;
            case 2: b++; break;
            case 3: c++; break;
            case 4: d++; break;
            case 5: e++; //cout<<str<<endl; break;
        }
        if(isPrivate) {
            //是合法IP,且判断是否私有IP
            priv++;
        }
    }
    printf("%d %d %d %d %d %d %d\n",a,b,c,d,e,err,priv);
    return 0;
}


编辑于 2021-06-24 12:26:52 回复(0)
按照题目的逻辑进行分类就行:
(1) 判断掩码的合法性,如果掩码不合法,直接错误数+1,判断下一行。
(2) 判断是不是【0.*.*.*】和【127.*.*.*】型,如果是就直接跳过。
(3) 依照题意对IP地址进行分类,但是对于ABC类,还需要判断一下是不是私有ip,如果是私有ip,则相应类别ip和私有ip的计数都要+1。
对于某个数,判断其二进制表示是否满足前面全是1后面全是0,只需要检查一下二进制串中是否有"01"这个子串就行了。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;

public class Main {
    static HashMap<String, Integer> counter = new HashMap<>();
    public static void main(String[] args) throws IOException {
        counter.put("A", 0);
        counter.put("B", 0);
        counter.put("C", 0);
        counter.put("D", 0);
        counter.put("E", 0);
        counter.put("Error", 0);
        counter.put("private", 0);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while((line = br.readLine()) != null){
            String[] params = line.trim().split("~");
            classifier(params[0].split("\\."), params[1].split("\\."));
        }
        System.out.println(counter.get("A") + " " + counter.get("B") + " " + counter.get("C") + " " + 
                           counter.get("D") + " " + counter.get("E") + " " + counter.get("Error") + " " + 
                           counter.get("private"));
    }
    
    private static void classifier(String[] ip, String[] mask) {
        if(!isRightMask(mask)){
            // 掩码不对,直接错误数加1,不再判断ip的类别
            counter.put("Error", counter.getOrDefault("Error", 0) + 1);
            return;
        }
        if(ip[0].length() == 0){
            counter.put("Error", counter.get("Error") + 1);
            return;
        }
        int num = Integer.parseInt(ip[0]);
        // 忽略【0.*.*.*】和【127.*.*.*】
        if(num == 0 || num == 127) return;
        // ip地址分类
        if(num >= 1 && num <= 126){
            // 检查是不是A类ip
            boolean isA = true;
            for(int i = 1; i < 4; i++){
                if(ip[i].length() == 0) {
                    isA = false;
                    break;
                }
                int temp = Integer.parseInt(ip[i]);
                if(temp < 0 || temp > 255){
                    isA = false;
                    break;
                }
            }
            if(isA){
                counter.put("A", counter.get("A") + 1);
                // 检查一下是不是私有ip
                if(num == 10)  counter.put("private", counter.get("private") + 1);
            }else
                counter.put("Error", counter.get("Error") + 1);
        }else if(num >= 128 && num <= 191){
            // 检查是不是B类ip
            boolean isB = true;
            for(int i = 1; i < 4; i++){
                if(ip[i].length() == 0) {
                    isB = false;
                    break;
                }
                int temp = Integer.parseInt(ip[i]);
                if(temp < 0 || temp > 255){
                    isB = false;
                    break;
                }
            }
            if(isB){
                counter.put("B", counter.get("B") + 1);
                // 检查一下是不是私有ip
                if(num == 172 && Integer.parseInt(ip[1]) >= 16 && Integer.parseInt(ip[1]) <= 31)
                    counter.put("private", counter.get("private") + 1);
            }else
                counter.put("Error", counter.get("Error") + 1);
        }else if(num >= 192 && num <= 223){
            // 检查是不是C类ip
            boolean isC = true;
            for(int i = 1; i < 4; i++){
                if(ip[i].length() == 0) {
                    isC = false;
                    break;
                }
                int temp = Integer.parseInt(ip[i]);
                if(temp < 0 || temp > 255){
                    isC = false;
                    break;
                }
            }
            if(isC){
                counter.put("C", counter.get("C") + 1);
                // 检查一下是不是私有ip
                if(num == 192 && Integer.parseInt(ip[1]) == 168)
                    counter.put("private", counter.get("private") + 1);
            }else
                counter.put("Error", counter.get("Error") + 1);
        }else if(num >= 224 && num <= 239){
            // 检查是不是D类ip
            boolean isD = true;
            for(int i = 1; i < 4; i++){
                if(ip[i].length() == 0) {
                    isD = false;
                    break;
                }
                int temp = Integer.parseInt(ip[i]);
                if(temp < 0 || temp > 255){
                    isD = false;
                    break;
                }
            }
            if(isD)
                counter.put("D", counter.get("D") + 1);
            else
                counter.put("Error", counter.get("Error") + 1);
        }else if(num >= 240 && num <= 255){
            // 检查是不是E类ip
            boolean isE = true;
            for(int i = 1; i < 4; i++){
                if(ip[i].length() == 0) {
                    isE = false;
                    break;
                }
                int temp = Integer.parseInt(ip[i]);
                if(temp < 0 || temp > 255){
                    isE = false;
                    break;
                }
            }
            if(isE)
                counter.put("E", counter.get("E") + 1);
            else
                counter.put("Error", counter.get("Error") + 1);
        }else
            counter.put("Error", counter.get("Error") + 1);
    }
    
    private static boolean isRightMask(String[] mask){
        // 全0和全255都不是合法的掩码
        if(Integer.parseInt(mask[0]) == 0)
            return false;
        if(mask[0].equals("255") && mask[1].equals("255") && mask[2].equals("255") && mask[3].equals("255"))
            return false;
        for(int i = 0; i < mask.length; i++){
            if(mask[i].length() == 0) return false;
            int temp = Integer.parseInt(mask[i]);
            if(temp >= 0 && temp < 255){
                String binstr = Integer.toBinaryString(Integer.parseInt(mask[i]));
                for(int k = 0; k < 8 - binstr.length(); k++)
                    binstr = "0" + binstr;
                if(binstr.indexOf("01") != -1){
                    // 前面不是连续的1
                    return false;
                }else{
                    // 前面是连续的1,检查一下后面是不是都是0
                    for(int j = i + 1; j < mask.length; j++)
                        if(!mask[j].equals("0")) return false;
                    return true;
                }
            }else if(temp == 255)
                continue;
            else
                return false;
        }
        return true;
    }
}

发表于 2021-03-28 14:52:43 回复(0)
有点冗长,但觉得挺清晰的, 有个疑问是时间做不到1ms,不知道哪里耗时
#include<stdio.h>
#include<string.h>

#define calInt(a,b,c,d) (((a*256 + b)*256 + c)*256 + d)

unsigned int AMin = calInt(1,0,0,0);
unsigned int AMax = calInt(126,255,255,255);
unsigned int BMin = calInt(128,0,0,0);
unsigned int BMax = calInt(191,255,255,255);
unsigned int CMin = calInt(192,0,0,0);
unsigned int CMax = calInt(223,255,255,255);
unsigned int DMin = calInt(224,0,0,0);
unsigned int DMax = calInt(239,255,255,255);
unsigned int EMin = calInt(240,0,0,0);
unsigned int EMax = calInt(255,255,255,255);

unsigned int P1Min = calInt(10,0,0,0);
unsigned int P1Max = calInt(10,255,255,255);
unsigned int P2Min = calInt(172,16,0,0);
unsigned int P2Max = calInt(172,31,255,255);
unsigned int P3Min = calInt(192,168,0,0);
unsigned int P3Max = calInt(192,168,255,255);

unsigned int arr2int(unsigned int *arr)
{
    unsigned int i,ret = 0;

    for(i = 0; i < 4; i++)
    {
        ret *= 256;
        ret +=arr[i];
    }
    return ret;
}

int rangeValidate(unsigned int *arr)
{
    int i;

    for(i = 0; i < 4; i++)
    {
        if(arr[i] >= 256)
            return 0;
    }
    return 1;
}
int maskValidate(unsigned int mask)
{
    int c1 = 0;
    
    if(mask != 0 && mask != 0xFFFFFFFF)
    {   
        mask = ~mask;
        mask += 1;
        while(mask)
        {
            if( mask & 1)
                c1++;
            mask >>= 1;
        }
    }    
    return c1 == 1;
}

int main()
{
    unsigned int ip[4] = {0}, mask[4] = {0},intIp,intMask;
    int A=0,B=0,C=0,D=0,E=0,error=0,private=0,format = 0;

    while( ( format = scanf( "%d.%d.%d.%d~%d.%d.%d.%d", 
                      &ip[0],&ip[1],&ip[2],&ip[3],&mask[0],&mask[1],&mask[2],&mask[3]) ) != EOF)
    {
        if( format != 8 )
        {
            error++;
            while(getchar() != '\n');
            continue;
        }
        
        if( rangeValidate( ip ) && rangeValidate( mask ))
        {
            intIp = arr2int( ip );
            intMask = arr2int( mask );
            if( maskValidate( intMask ) )
            {
                if( intIp >= AMin && intIp <= AMax )
                    A++;
                if( intIp >= BMin && intIp <= BMax )
                    B++;
                if( intIp >= CMin && intIp <= CMax )
                    C++;
                if( intIp >= DMin && intIp <= DMax )
                    D++;
                if( intIp >= EMin && intIp <= EMax )
                    E++;
                
                if( ( intIp >= P1Min && intIp <= P1Max ) || 
                    ( intIp >= P2Min && intIp <= P2Max ) || 
                    ( intIp >= P3Min && intIp <= P3Max ) )
                    private++;
            }
            else
            {
                error++;
            }
        }
        else
        {
            error++;
        }
    }
    printf( "%d %d %d %d %d %d %d", A,B,C,D,E,error,private );
    return 0;
}

编辑于 2021-01-22 21:13:39 回复(0)
import java.util.*;
public class Main {
    public static final long[] boundA = new long[] {
            0x01000000L,
            0x7EFFFFFFL
    };
    public static final long[] boundB = new long[] {
            0x80000000L,
            0xBFFFFFFFL
    };
    public static final long[] boundC = new long[] {
            0xC0000000L,
            0xDFFFFFFFL
    };
    public static final long[] boundD = new long[] {
            0xE0000000L,
            0xEFFFFFFFL
    };
    public static final long[] boundE = new long[] {
            0xF0000000L,
            0xFFFFFFFFL
    };
    public static final long[][] ignored = new long[][] {
            new long[]{
                    0x00000000L,
                    0x00FFFFFFL
            },
            new long[] {
                    0x7F000000L,
                    0x7FFFFFFFL
            }
    };
    public static final long[][] boundPrivates = new long[][] {
            new long[] {
                    0x0A000000L,
                    0x0AFFFFFFL
            },
            new long[] {
                    0xAC0F0000L,
                    0xAC1F0000L
            },
            new long[] {
                    0xC0A80000L,
                    0xC0A8FFFFL
            }
    };
    public static final long[] validMasks = new long[] {
            (0xFFFFFFFFL << 1) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 2) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 3) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 4) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 5) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 6) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 7) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 8) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 9) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 10) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 11) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 12) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 13) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 14) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 15) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 16) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 17) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 18) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 19) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 20) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 21) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 22) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 23) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 24) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 25) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 26) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 27) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 28) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 29) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 30) & 0xFFFFFFFFL,
            (0xFFFFFFFFL << 31) & 0xFFFFFFFFL


    };
    public static boolean rightMask(String maskstr) {
        long mask = IP2Int(maskstr);
        if(mask == -1) {
            return false;
        }
        for(long i : validMasks) {
            if( i == mask) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean isPrivate(String ipstr) {
        long ip = IP2Int(ipstr);
        return (ip >= boundPrivates[0][0] && ip <= boundPrivates[0][1]) ||
                (ip >= boundPrivates[1][0] && ip <= boundPrivates[1][1]) ||
                (ip >= boundPrivates[2][0] && ip <= boundPrivates[2][1]) ;
    }
    
    public static int getIPType(long ip) {
        if(ip >= boundA[0] && ip <= boundA[1]) {
            return 1;
        } else if(ip >= boundB[0] && ip <= boundB[1]) {
            return 2;
        } else if(ip >= boundC[0] && ip <= boundC[1]) {
            return 3;
        } else if(ip >= boundD[0] && ip <= boundD[1]) {
            return 4;
        } else if(ip >= boundE[0] && ip <= boundE[1]) {
            return 5;
        } else if((ip >= ignored[0][0] && ip <= ignored[0][1]) ||
                (ip >= ignored[1][0] && ip <= ignored[1][1])) {
            return -2;
        }
        else {
            return 6;
        }
    }
    public static long IP2Int(String str) {
        long result = -1;
        String[] split = str.split("\\.");
        if(split.length != 4) {
            return result;
        }
        result = 0;
        for(String part : split) {
            try {
                result = (result << 8 | Integer.parseInt(part));
            } catch (NumberFormatException ex) {
                ex.printStackTrace();
                result = -1;
                break;
            }
        }
        return result;
    }
    public static int identifyIP(String ipstr) {
        int err = 0;
        long ip = IP2Int(ipstr);
        if(ip == -1) {
            err = 6;
        } else {
            err = getIPType(ip);
        }

        return err;
    }

    public static void main(String[] args) {
        int A = 0; //1
        int B =0 ; //2
        int C = 0; //3
        int D = 0; //4
        int E = 0; //5
        int ERROR = 0; //6
        int PRIVATE = 0; //7
        Scanner sc = new Scanner(System.in);
        while(true) {
            String str;
            if(sc.hasNextLine()) {
                str = sc.nextLine();
            } else {
                break;
            }
            String[] split = str.split("~");
            String ip = split[0];
            String mask = split[1];
            if(!rightMask(mask)) {
                ERROR++;
            } else {
                int res = identifyIP(ip);
                switch(res) {
                    case 1: A++;break;
                    case 2: B++;break;
                    case 3: C++;break;
                    case 4: D++;break;
                    case 5: E++;break;
                    case 6: ERROR++;break;
                    default: break;
                }
                if(res != 6) {
                    if(isPrivate(ip)) {
                        PRIVATE++;
                    }
                }
            }  
        }
        System.out.printf("%d %d %d %d %d %d %d\n",A, B, C, D, E, ERROR, PRIVATE);
    }
}

引用一下注意的点
当子网掩码错误时,不在判断ip是否有效,错误直接加一, 进行下次循环
这个点第一次是没发现的
实际上如果把IP地址转化到uint32,这个题目就很简单了,不过java没有uint32,用long代替。
子网掩码直接使用穷举方法打表。
发表于 2020-09-26 18:13:45 回复(0)
def checkyanma(yanma01str):
    if yanma01str[0]=='0'&nbs***bsp;yanma01str[-1]=='1':
        return False
    ing = 1
    for c in yanma01str:
        if c=='1' and ing==0:
            return False
        if c=='0':
            ing=0
    return True

def checkip(iplist):
    kind, si = 5, 0
    for num in iplist:
        if num<0&nbs***bsp;num>255:
            return kind, si
    if 1<=iplist[0]<=126: kind = 0
    elif 128<=iplist[0]<=191: kind = 1
    elif 192<=iplist[0]<=223: kind = 2
    elif 224<=iplist[0]<=239: kind = 3
    else: kind = 4
    if iplist[0]==10: si = 1
    elif iplist[0]==172 and 16<=iplist[1]<=31: si = 1
    elif iplist[0]==192 and iplist[1]==168: si = 1
    return kind, si

def solution(record):
    ans = [0,0,0,0,0,0,0]
    for _ in record:
        ipstr, yanmastr = _[0], _[1]
        iplist = list(map(int, [x for x in ipstr.split('.') if x]))
        yanmalist = list(map(int, [x for x in yanmastr.split('.') if x]))
        if len(iplist)!=4:
            ans[5] += 1
            continue
        
        if len(yanmalist)!=4:
            ans[5] += 1
            continue
        yanma01str = ''.join(list(map(lambda x:bin(x)[2:].rjust(8, '0'), yanmalist)))
        if not checkyanma(yanma01str):
            ans[5] += 1
            continue
        # 排除0和127开头
        if iplist[0]==0&nbs***bsp;iplist[0]==127: continue
        kind, si = checkip(iplist)
        ans[kind]+=1
        ans[-1]+=si
    return ' '.join(list(map(str, ans)))

import sys
while True:
    try:
        record = []
        #while True:
        for line in sys.stdin:
            # inputlist = sys.stdin.readline()
            # inputlist = input()
            # if inputlist=='':
             #     break
            record.append(list(line.split('~')))
        if record==[]:
            break
        else:
            print(solution(record))
    except:
        break

最坑的就是127的时候直接跳过,但掩码错了其实不能跳过,要错误加一的。
输入也不能用input,像这种没有制定输入多少行的要用for line in sys.stdin:


发表于 2020-08-18 11:42:07 回复(2)
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <string>
//使用网络库函数判断 ip是否合规    --    学到了
//1、使用fgets函数读入一行数据
//2、对每一行数据进行按照~切割成 ip 和子网掩码
//3、判断子网掩码(本题是 不能全1,且前面是连续的1后面是连续的0),则可以用子网掩码取反+1,则二进制只有一个1个1
//处理过的子网掩码再和处理过的子网掩码-1做与操作,若为0 则子网掩码ok
//4、判断ip的范围,来进行相应的变量计数即可


using namespace std;

int validmask(char * mask)
{
    unsigned int n[4],res = 0;
    int i ;
    sscanf(mask,"%u.%u.%u.%u",&n[3],&n[2],&n[1],&n[0]);
    if(n[3] == 255 && n[2] == 255 && n[1] == 255 && n[0]== 255)
        return 0;
    for(i = 0;i<4;i++)
    {
        res += n[i]<<(i*8);
    }
    res = ~res +1;
    if((res & (res - 1)) == 0)    return 1;
    return 0;
}

int main()
{
    char str[50];
    int a = 0,b=0,c=0,d=0,e=0,err=0,pri=0;
    while(fgets(str,50,stdin))
    {
        char *p = str;
        char ip[2][20];
        int i = 0;
        int maskflag = 0;
        while((p = strtok(p,"~") )!= NULL)
        {
            strcpy(ip[i],p);
            i++;
            p = NULL;
            if(i == 2)    i=0;
        }
        maskflag = validmask(ip[1]);
        if(maskflag)
        {
            struct in_addr st;
            unsigned int ip1,ip2;
            int valid = inet_pton(AF_INET,ip[0],(void *)&st);
            sscanf(ip[0],"%u.%u",&ip1,&ip2);
            if(valid)
            {
                if(ip1>=1 && ip1 <=126)
                    a++;
                else if(ip1>=128 && ip1 <=191)
                    b++;
                else if(ip1>=192 && ip1 <=223)
                    c++;
                else if(ip1>=224 && ip1 <=239)
                    d++;
                else if(ip1>=240 && ip1 <=255)
                    e++;
                if(ip1==10
                        || (ip1==172 && ip2 >=16 &&ip2 <=31)
                        || (ip1==192 && ip2 ==168))
                    pri ++;
            }else
                err++;
        }else
        {
            err++;
        }
    }
    cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e<<" "<<err<<" "<<pri<<endl;
}

发表于 2020-07-14 11:28:16 回复(0)
import re
import sys


def is_legal_ip(ip):
    if not ip:
        return False

    pattern = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
    if not pattern.match(ip):
        return False

    segments = ip.split(".")
    for s in segments:
        s = int(s)
        if s < 0&nbs***bsp;s > 255:
            return False

    return True


def is_private_ip(ip):
    if not is_legal_ip(ip):
        return False

    segments = ip.split(".")
    s0 = int(segments[0])
    s1 = int(segments[1])
    if s0 == 10:
        return True
    if s0 == 172:
        if 16 <= s1 <= 31:
            return True
    if s0 == 192 and s1 == 168:
        return True

    return False


def is_legal_mask(mask):
    if not is_legal_ip(mask):
        return False

    bin_mask = "".join(
        [format(int(segment), 'b').zfill(8) for segment in mask.split(".")])
    first_zero_idx = bin_mask.find("0")
    last_one_idx = bin_mask.rfind("1")
    if first_zero_idx == -1&nbs***bsp;last_one_idx == -1:
        return False
    if last_one_idx > first_zero_idx:
        return False
    return True


def ip_category(ip):
    if not is_legal_ip(ip):
        raise ValueError("Illegal IP")

    s0 = int(ip.split(".")[0])
    if 1 <= s0 <= 126:
        return "A"
    if 128 <= s0 <= 191:
        return "B"
    if 192 <= s0 <= 223:
        return "C"
    if 224 <= s0 <= 239:
        return "D"
    if 240 <= s0 <= 255:
        return "E"

    raise ValueError("Unknown category")


if __name__ == "__main__":
    a = 0
    b = 0
    c = 0
    d = 0
    e = 0
    f = 0
    p = 0
    for line in sys.stdin:
        ip, mask = line.strip().split("~")
        if not is_legal_ip(ip)&nbs***bsp;not is_legal_mask(mask):
            f += 1
        else:
            if is_private_ip(ip):
                p += 1
            try:
                category = ip_category(ip)
                if category == "A":
                    a += 1
                if category == "B":
                    b += 1
                if category == "C":
                    c += 1
                if category == "D":
                    d += 1
                if category == "E":
                    e += 1
            except ValueError:
                pass
    print(a, b, c, d, e, f, p)

发表于 2020-07-14 10:19:40 回复(0)
错误提示没有输入输出数据的问题该怎么解决?
发表于 2020-05-04 18:06:02 回复(0)
import java.util.Scanner;

public class Main{
    public static int pr;
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int A=0,B=0,C=0,E=0,D=0,error=0;
        while(sc.hasNext()){
            String s=sc.nextLine();
            String sArr[]=s.split("~");
            if(panduanyanma(sArr[1])){
                char k=pandan***(sArr[0],sArr[1]);
                if(k=='A'){A++;}else if(k=='B'){B++;}else if(k=='C'){C++;}
                else if(k=='D'){D++;}else if(k=='E'){E++;}
                else if(k=='n'){error++;}else{;}
                
            }else{
                error++;
            }
        }
        System.out.println(A+" "+B+" "+C+" "+D+" "+E+" "+error+" "+pr);
    }
    public static boolean panduanyanma(String s){
        String sArr[]=s.split("\\.");
        int k[]=new int [sArr.length];
        for(int i=0;i<sArr.length;i++){
            //System.out.println(sArr[i].length()>3);
            if(sArr[i].length()<=0||sArr[i].length()>3)
            {  return false;}
            k[i]=Integer.parseInt(sArr[i]);
            //System.out.println(k[i]);
           if(k[i]>255)return false;
           if(i>0&&k[i-1]!=255&&k[i]!=0)return false;
           if(i>0&&(k[i-1]==255)&&(k[i]!=0&&k[i]!=128&&k[i]!=192&&k[i]!=224&&k[i]!=240&&k[i]!=248&&k[i]!=252&&k[i]!=254&&k[i]!=255))
           { return false;}
           if(i==sArr.length-1&&k[i]==255)return false;

        }
        return true;
    }
    public static char pandan***(String s,String d){
        String sArr[]=s.split("\\.");
        int k[]=new int [sArr.length];
        String dArr[]=d.split("\\.");
        int kd[]=new int [dArr.length];
        for(int i=0;i<sArr.length;i++){
            //System.out.println(sArr[i].length()>3);
            if(sArr[i].length()<=0||sArr[i].length()>3)
            {  return 'n';}
            k[i]=Integer.parseInt(sArr[i]);
            kd[i]=Integer.parseInt(dArr[i]);
            if(k[i]>255)return 'n';
            
            k[i]=k[i]&kd[i];
            
                
            
        }
        if(k[0]==10&&k[1]>=0&&k[2]>=0&&k[3]>=0&&k[1]<=255&&k[2]<=255&&k[3]<=255){
            pr++;
        }
        if(k[0]==172&&k[1]>=16&&k[2]>=0&&k[3]>=0&&k[1]<=31&&k[2]<=255&&k[3]<=255){
            pr++;
        }
        if(k[0]==192&&k[1]==168&&k[2]>=0&&k[3]>=0&&k[2]<=255&&k[3]<=255){
            pr++;
            
        }
        if(k[0]>=1&&k[0]<=126&&k[1]>=0&&k[2]>=0&&k[3]>=0&&k[1]<=255&&k[2]<=255&&k[3]<=255){
            return 'A';
        }
        if(k[0]>=128&&k[0]<=191&&k[1]>=0&&k[2]>=0&&k[3]>=0&&k[1]<=255&&k[2]<=255&&k[3]<=255){
            return 'B';
        }
        if(k[0]>=192&&k[0]<=223&&k[1]>=0&&k[2]>=0&&k[3]>=0&&k[1]<=255&&k[2]<=255&&k[3]<=255){
            return 'C';
        }
        if(k[0]>=224&&k[0]<=239&&k[1]>=0&&k[2]>=0&&k[3]>=0&&k[1]<=255&&k[2]<=255&&k[3]<=255){
            return 'D';
        }
        if(k[0]>=240&&k[0]<=255&&k[1]>=0&&k[2]>=0&&k[3]>=0&&k[1]<=255&&k[2]<=255&&k[3]<=255){
            return 'E';
        }
        return 'o';
    }
}
使用两个方法,一个是判断子网掩码是否符合要求,其符合才会去考虑ip地址。如果子网掩码不符合,那么ip地址就也算错误,不做考虑。另一个方法是判断地址是否符合,这里面直接做与,然后判断每一个数字对应的是哪个地址段。
发表于 2020-04-29 23:13:17 回复(0)
c语言版
#include <stdio.h>
#include <string.h>
int main(){
	char s[20];
	int i,j,len,a=0,b=0,c=0,d=0,e=0,err=0,pri=0,flag=0,num=0,p=0,ip[8];
	bool error,fg;
	while(scanf("%s",s)!=EOF){
		p=0;flag=0;error=false;fg=false;//p指向ip[p],flag标记数字字符起始位置,error判断输入是否有错误,fg子网掩码是否正确
		len=strlen(s);
		for(i=0;i<len+1;i++){   //提起输入字符串里的数字并且判断输入格式是否正确
				if(s[i]>='0'&&s[i]<='9')
					continue;
				else if(s[i]=='.'||s[i]=='~'||s[i]=='\0'){
					num=0;
					for(j=flag;j<i;j++)
						num=num*10+(s[j]-'0');
					ip[p++]=num;
					flag=i+1;
					if(num<0||num>255){
						err++;
						error=true;     //格式错误
						break;
					}
					if(s[i]!='\0')
					if(s[flag]<'0'||s[flag]>'9'){
						err++;
						error=true;
						break;
					}
				}
				else{
					err++;
					error=true;
					break;
				}
		}
		if(!error){
			num=0;
			if(ip[4]==0||ip[7]==255)  //判断子网掩码是否正确
				err++;
			else{
				for(i=4;i<=7;i++){
					if(ip[i]==255)
						continue;
					for(j=i+1;j<=7;j++)
						num+=ip[j];
					if((ip[i]==254||ip[i]==252||ip[i]==248||ip[i]==240||ip[i]==224||ip[i]==192||ip[i]==128||ip[i]==0)&&num==0)
						fg=true;   //子网掩码正确
						else
						err++;
					break;
				}
			}
			if(fg){  //子网掩码正确的情况下判断是哪一类ip
				if(ip[0]>=1&&ip[0]<=126) a++;
				else if(ip[0]>=128&&ip[0]<=191) b++;
				else if(ip[0]>=192&&ip[0]<=223) c++;
				else if(ip[0]>=224&&ip[0]<=239) d++;
				else if(ip[0]>=240&&ip[0]<=255) e++;
				if(ip[0]==10||(ip[0]==172&&ip[1]>=16&&ip[1]<=31)||(ip[0]==192&&ip[1]==168))
					pri++;
			}
		}
	}
	printf("%d %d %d %d %d %d %d\n",a,b,c,d,e,err,pri);
	return 0;
}

发表于 2020-02-11 17:44:22 回复(0)
import java.util.Scanner;

/**
 * @author sunlichao
 * @date 2019/12/29
 */
public class Main {

    public static long ipToInt(String ip) {
        String[] p = ip.split("\\.");
        if (p.length < 4) {
            return -1;
        }
        long result = 0;
        try {
            for (int i = 0; i < 4; i++) {
                long t = Integer.parseInt(p[i]);
                if (t < 0 || t > 255) {
                    return -1;
                }
                result |= (t << (8 * (3 - i)));
            }
        } catch (NumberFormatException ex) {
            return -1;
        }

        return result;
    }

    public static boolean validMask(String mask) {
        long a = 0L;
        long r = ipToInt(mask);

        int m = (int) r;
        if (m == -1) {
            return false;
        }
        while ((m <<= 1) < 0) {
        }

        if (m == 0) {
            return true;
        } else {
            return false;
        }

    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long[][] data = {
                {ipToInt("1.0.0.0"), ipToInt("126.255.255.255")},
                {ipToInt("128.0.0.0"), ipToInt("191.255.255.255")},
                {ipToInt("192.0.0.0"), ipToInt("223.255.255.255")},
                {ipToInt("224.0.0.0"), ipToInt("239.255.255.255")},
                {ipToInt("240.0.0.0"), ipToInt("255.255.255.255")},
        };
        long[][] personal = {
                {ipToInt("10.0.0.0"), ipToInt("10.255.255.255")},
                {ipToInt("172.16.0.0"), ipToInt("172.31.255.255")},
                {ipToInt("192.168.0.0"), ipToInt("192.168.255.255")},
        };

        int[] abcd = new int[5];
        int wrongIp = 0;
        int tmp;
        int personalCount = 0;
        while (scanner.hasNext()) {
            String line = scanner.nextLine();
            String[] pre = line.split("~");
            long ip = ipToInt(pre[0]);

            if (!validMask(pre[1])) {
                wrongIp++;
            } else {
                if (ip != -1) {
                    for (int i = 0; i < data.length; i++) {
                        if (ip >= data[i][0] && ip <= data[i][1]) {
                            abcd[i]++;
                            break;
                        }
                    }
                } else {
                    wrongIp++;
                }


                for (int i = 0; i < personal.length; i++) {
                    if (ip >= personal[i][0] && ip <= personal[i][1]) {
                        personalCount++;
                        break;
                    }
                }
            }
        }

        System.out.println(abcd[0] + " " + abcd[1] + " " + abcd[2] + " " + abcd[3] + " " + abcd[4] + " " + wrongIp + " " + personalCount);
    }
}


编辑于 2019-12-30 01:44:43 回复(2)
先说几个坑:
  1. 按题意掩码255.255.255.255是错误的,实际应是正确,至少有30%的测试集包含这一掩码;
  2. 掩码和IP同时错误只计一次
  3. 非A/B/C/D/E的非法IP不算错误,竟然有60%的测试集包含这样的IP,残念;
这个题的测试集并不好,建议修改一下,完全判断的代码只能10%AC也是醉了。
整体思路
其实题意比较简单,按部就班就好:判断字符格式 -> 判断掩码值 -> 判断IP种类并累加
代码思路
  • 判断掩码正确性可以将掩码转换为32位无符号数后,计算掩码的非。把问题转化为判断是否从低位开始是连续的1。该问题又等价于判断数字是否为2n-1,可以用 `x & (x + 1) == 0` 来判断;
  • 判断IP用分治法应该是可以的,但我比较习惯转换为32位数之后直接比较,判断是否在范围内只需比较两次;
  • 判断字符格式用正则可能是最方便的,C++不能用Boost真的伤= =差点就用python写了。
其他细节看代码吧,注释少了点不过重要的点我上面都写了。
#include <bits/stdc++.h>

size_t countNum[7];

unsigned int transformIP(std::string _IP) noexcept(false) {
    unsigned char data[4];
    std::string str[4];
    memset(data, 0, sizeof(data));

    for(size_t i = 0; i < 3; i++) {
        auto pos = _IP.find('.');
        if(pos == std::string::npos || pos == 0)
            throw std::string("error");
        str[i] = _IP.substr(0, pos);
        _IP = _IP.substr(pos + 1);
    }
    if(_IP.empty())throw std::string("error");
    str[3] = _IP;
    for(size_t i = 0; i < 4; i++) {
        for(const char ch : str[i]) {
            if(ch < '0' || ch > '9')
                throw std::string("error");
            data[i] *= 10;
            data[i] += ch - '0';
        }
        if(data[i] > 255)throw std::string("error");
    }
    return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
}

void processLine(const std::string& _Line) {
    auto pos = _Line.find('~');
    if(pos == std::string::npos) {
        countNum[5]++;    // wrong line
        return;
    }
    std::string mask = _Line.substr(pos + 1);
    std::string ip = _Line.substr(0, pos);
    try {
        unsigned int ipVal = transformIP(ip);
        unsigned int maskVal = transformIP(mask);
        unsigned int tmp = ~maskVal;
//        if(tmp & (tmp + 1)) {    // 255.255.255.255 is actually valid
        if(!tmp || tmp & (tmp + 1)) {
            countNum[5]++;    // wrong mask
            return;
        }
        static constexpr unsigned int A_BEGIN = 1u << 24;
        static constexpr unsigned int A_END = (127u << 24) - 1u;
        static constexpr unsigned int B_BEGIN = 128u << 24;
        static constexpr unsigned int B_END = (192u << 24) - 1u;
        static constexpr unsigned int C_BEGIN = 192u << 24;
        static constexpr unsigned int C_END = (224u << 24) - 1u;
        static constexpr unsigned int D_BEGIN = 224u << 24;
        static constexpr unsigned int D_END = (240u << 24) - 1u;
        static constexpr unsigned int E_BEGIN = 240u << 24;
        static constexpr unsigned int E_END = 0xFFFFFFFFu;
        static constexpr unsigned int SP1_BEGIN = 10u << 24;
        static constexpr unsigned int SP1_END = (11u << 24) - 1u;
        static constexpr unsigned int SP2_BEGIN = (172u << 24) | (16u << 16);
        static constexpr unsigned int SP2_END = ((172u << 24) | (32u << 16)) - 1u;
        static constexpr unsigned int SP3_BEGIN = (192u << 24) | (168u << 16);
        static constexpr unsigned int SP3_END = ((192u << 24) | (169u << 16)) - 1u;

        if(ipVal >= A_BEGIN && ipVal <= A_END) {
            countNum[0]++;
            if(ipVal >= SP1_BEGIN && ipVal <= SP1_END) {
                countNum[6]++;
            }
        } else if(ipVal >= B_BEGIN && ipVal <= B_END) {
            countNum[1]++;
            if(ipVal >= SP2_BEGIN && ipVal <= SP2_END) {
                countNum[6]++;
            }
        } else if(ipVal >= C_BEGIN && ipVal <= C_END) {
            countNum[2]++;
            if(ipVal >= SP3_BEGIN && ipVal <= SP3_END) {
                countNum[6]++;
            }
        } else if(ipVal >= D_BEGIN && ipVal <= D_END) {
            countNum[3]++;
        } else if(ipVal >= E_BEGIN && ipVal <= E_END) {
            countNum[4]++;
        } /* else {
            std::cout << _Line << " is invalid!" << std::endl;
            countNum[5]++;
        } */
        return;
    } catch(std::string& ex) {
        countNum[5]++;    // wrong format
        return;
    }
}

int main(int argc, const char* argv[]) {
    std::ios::sync_with_stdio(false);

    std::string buffer;
    while(std::cin >> buffer) {
        processLine(buffer);
    }
    std::cout << countNum[0];
    for(size_t i = 1; i < 7; i++)
        std::cout << ' ' << countNum[i];

    return EXIT_SUCCESS;
}


编辑于 2019-08-28 14:16:18 回复(1)