首页 > 试题广场 >

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

[编程题]识别有效的IP地址和掩码并进行分类统计
  • 热度指数:376541 时间限制: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 更新题面。
#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)
#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)
按照题目的逻辑进行分类就行:
(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)
//牛客有BUG,C++提交格式不对,将就看吧!
//判断子网掩码那部分可以参考
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int numberOf1(int n)
//计算二进制串中1的个数,用于辅助判断子网掩码是否合格
{
    int count = 0;
    while (n)
    {
        ++count;
        n = (n - 1)&n;
    }
    return count;
}
int main()
{
    int AA = 0;
    int BB = 0;
    int CC = 0;
    int DD = 0;
    int EE = 0;
    int Error = 0;
    int privateIP = 0;
    string str;
    while (getline(cin, str))
    {

        int numOfDot = 0;
        int numOfTilde = 0;
        vector<int> indexOfDot;
        vector<int> indexOfTilde;
        for (int i = 0; i < str.size(); i++)
        {
            if (str[i] == '.')
            {
                numOfDot++;
                indexOfDot.push_back(i);
            }
            if (str[i] == '~')
            {
                numOfTilde++;
                indexOfTilde.push_back(i);
            }
        }
        //先查格式:是否满足有六个.和一个~
        if (numOfDot != 6 || numOfTilde != 1)
        {
            Error++;
            continue;
        }
        string ip1 = str.substr(0, indexOfDot[0]);
        string ip2 = str.substr(indexOfDot[0] + 1, indexOfDot[1] - indexOfDot[0] - 1);
        string ip3 = str.substr(indexOfDot[1] + 1, indexOfDot[2] - indexOfDot[1] - 1);
        string ip4 = str.substr(indexOfDot[2] + 1, indexOfTilde[0] - indexOfDot[2] - 1);
        string mask1 = str.substr(indexOfTilde[0] + 1, indexOfDot[3] - indexOfTilde[0] - 1);
        string mask2 = str.substr(indexOfDot[3] + 1, indexOfDot[4] - indexOfDot[3] - 1);
        string mask3 = str.substr(indexOfDot[4] + 1, indexOfDot[5] - indexOfDot[4] - 1);
        string mask4 = str.substr(indexOfDot[5] + 1, str.size() - indexOfDot[5] - 1);
        int IP1 = stoi(ip1);
        int IP2 = stoi(ip2);
        int IP3 = stoi(ip3);
        int IP4 = stoi(ip4);
        //第二查:IP地址是否在0-255之间
        if ((IP1 < 0 || IP1 > 255) || (IP2 < 0 || IP2 > 255) || 
            (IP3 < 0 || IP3 > 255) || (IP4 < 0 || IP4 > 255))
        {
            Error++;
            continue;
        }
        int MASK1 = stoi(mask1);
        int MASK2 = stoi(mask2);
        int MASK3 = stoi(mask3);
        int MASK4 = stoi(mask4);
        //第三查:子网掩码是否在0-255之间,特别注意最后一位掩码不能是255
        if ((MASK1 < 0 || MASK1 > 255) || (MASK2 < 0 || MASK2 > 255) || 
            (MASK3 < 0 || MASK3 > 255) || (MASK4 < 0 || MASK4 >= 255))
        {
            Error++;
            continue;
        }
        //用二进制位***作的方法,判断一个串是否满足1111...00的模式
        unsigned long long bigIpNumber = 
            MASK1 * (1<<24) + MASK2 * (1<<16) + MASK3 * (1<<8) + MASK4;
        if (numberOf1((~bigIpNumber) + 1) != 1)//子网掩码不合格
        {
            Error++;
            continue;
        }
        //统计ABCDE类地址
        if ((IP1 >= 0 && IP1 <= 255) && (IP2 >= 0 && IP2 <= 255) && 
            (IP3 >= 0 && IP3 <= 255) && (IP4 >= 0 && IP4 <= 255))
        {
            if (IP1 >= 1 && IP1 <= 126)
                AA++;
            else if (IP1 >= 128 && IP1 <= 191)
                BB++;
            else if (IP1 >= 192 && IP1 <= 223)
                CC++;
            else if (IP1 >= 224 && IP1 <= 239)
                DD++;
            else if(IP1 >= 240 && IP1 <= 255)
                EE++;
        }
        else
        {
            Error++;
            continue;
        }
        //统计私有地址
        if (IP1 == 10)
            privateIP++;
        else if (IP1 == 172 && (IP2 >= 16 && IP2 <= 31))
            privateIP++;
        else if (IP1 == 192 && IP2 == 168)
            privateIP++;
    }
    cout << AA << " ";
    cout << BB << " ";
    cout << CC << " ";
    cout << DD << " ";
    cout << EE << " ";
    cout << Error << " ";
    cout << privateIP << endl;
}

编辑于 2018-09-22 21:54:49 回复(0)
#include<iostream>
#include<string>
#include<sstream>
#include<vector>
using namespace std;

unsigned int A[2] = {0x01000000,0x7EFFFFFF}; //A类网地址范围
unsigned int B[2] = {0x80000000,0xBFFFFFFF}; //B类网地址范围
unsigned int C[2] = {0xC0000000,0xDFFFFFFF}; //C类网地址范围
unsigned int D[2] = {0xE0000000,0xEFFFFFFF}; //D类网地址范围
unsigned int E[2] = {0xF0000000,0xFFFFFFFF}; //E类网地址范围
unsigned int F[2] = {0x0A000000,0x0AFFFFFF}; //私网地址范围1
unsigned int G[2] = {0xAC100000,0xAC1FFFFF}; //私网地址范围2
unsigned int H[2] = {0xC0A80000,0xC0A8FFFF}; //私网地址范围3

//将地址/掩码转换为unsigned int
unsigned int string2int(string str)
{
    int io = 0;
    unsigned int mas = 0;
    while((int)(str.find('.',io))>=0)
    {
        int i = str.find('.',io);
        if(i-io==0)
            return 0;
        istringstream ss;
        ss.str(str.substr(io,i-io));
        io = i+1;
        unsigned int temp;
        ss>>temp;
        mas<<=8;
        mas|=temp;
    }
    istringstream ss;
    ss.str(str.substr(io));
    unsigned int temp;
    ss>>temp;
    mas<<=8;
    mas|=temp;
    return mas;
}
//检查掩码是否合法
bool checkmask(unsigned int mas)
{
    //255.255.255.255的掩码的非法的
    if(mas==0xFFFFFFFF)
        return false;
    unsigned int flag = 1;
    while(flag!=0)
    {
        if((mas&flag)==0)
        {
            flag<<=1;
            continue;
        }
        else 
        {
            while(flag!=0)
            {
                if((mas&flag)==0)
                    return false;
                flag<<=1;
            }
        }
    }
    return true;
}
//寻找IP的类别
int checkipad(unsigned int ipa)
{
    if(ipa>=A[0]&&ipa<=A[1])
    {
        if(ipa>=F[0]&&ipa<=F[1])
            return 11;
        return 1;
    }
    else if(ipa>=B[0]&&ipa<=B[1])
    {
        if(ipa>=G[0]&&ipa<=G[1])
            return 12;
        return 2;
    }
    else if(ipa>=C[0]&&ipa<=C[1])
    {
        if(ipa>=H[0]&&ipa<=H[1])
            return 13;
        return 3;
    }
    else if(ipa>=D[0]&&ipa<=D[1])
        return 4;
    else if(ipa>=E[0]&&ipa<=E[1])
        return 5;
    return 0;
}
//主函数
int main()
{
    string str;
    vector<string> ipad;
    vector<string> mask;
    vector<int> res(7,0);
    while(getline(cin,str))
    {
        int pos = str.find('~');
        ipad.push_back(str.substr(0,pos));
        mask.push_back(str.substr(pos+1));
    }
    {
        unsigned int i;
        vector<int> ip;
        vector<int> im;
        for(i=0;i<ipad.size();++i)
        {
            unsigned int tep = string2int(ipad[i]);
            unsigned int tem = string2int(mask[i]);
            if(tep==0||tem==0)
            {
                res[5] += 1;
                continue;
            }
            else
            {
                int bop = checkipad(tep);
                bool bom = checkmask(tem);
                if(!bom)
                {
                    res[5] += 1;
                    continue;
                }
                else
                {
                    switch(bop)
                    {
                    case 1:
                        res[0] += 1;
                        break;
                    case 2:
                        res[1] += 1;
                        break;
                    case 3:
                        res[2] += 1;
                        break;
                    case 4:
                        res[3] += 1;
                        break;
                    case 5:
                        res[4] += 1;
                        break;
                    case 11:
                        res[0] += 1;
                        res[6] += 1;
                        break;
                    case 12:
                        res[1] += 1;
                        res[6] += 1;
                        break;
                    case 13:
                        res[2] += 1;
                        res[6] += 1;
                        break;
                    }
                }
            }
        }
    }
    unsigned int i;
    for(i=0;i<res.size();++i)
    {
        cout<<res[i];
        if(i<res.size()-1)
            cout<<' ';
    }
    cout<<endl;
    return 0;
}

编辑于 2018-08-06 22:53:20 回复(0)
#include<iostream>
#include<vector>
#include<string>
#include<sstream>
 
using namespace std;
vector<string> split(string str,char del)
{
    stringstream ss(str);
    string tok;
    vector<string> ret;
    while(getline(ss,tok,del))
    {
        if(tok > "")
            ret.push_back(tok);
    }
    return ret;
}
 
int main()
{
    string all;
    int result[7]={0};
    while(getline(cin,all))
    {
        vector<string> ipyanma;
        ipyanma = split(all,'~');
        vector<string> ip,yanma;
        ip = split(ipyanma[0],'.');
        yanma = split(ipyanma[1],'.');
        unsigned int yyy=0,yuan=0,flag=0;
        if(ip.size() == 4 && yanma.size() == 4)
        {
            for(int kk=0;kk<4;kk++)
            {
                unsigned int temp11= atoi(yanma[kk].c_str());
                yyy += temp11 << ((3-kk)*8);
            }
            yuan = yyy;
            yyy = (~yyy) +1;
            flag = yyy & (yyy-1);
            if((flag ==0) && (yuan != 0xffffffff) && (yuan != 0) )
            {
                if(atoi(ip[0].c_str()) >= 1 && atoi(ip[0].c_str()) <= 126)
                    result[0] += 1;
                if(atoi(ip[0].c_str())>=128 && atoi(ip[0].c_str())<=191)
                    result[1] += 1;
                if(atoi(ip[0].c_str())>=192 && atoi(ip[0].c_str())<=223)
                    result[2] += 1;
                if(atoi(ip[0].c_str())>=224 && atoi(ip[0].c_str())<=239)
                    result[3] += 1;
                if(atoi(ip[0].c_str())>=240 && atoi(ip[0].c_str())<=255)
                    result[4] += 1;
                if((atoi(ip[0].c_str())>=10 && atoi(ip[0].c_str())<=10) ||
                   (atoi(ip[0].c_str())>=172 && atoi(ip[1].c_str())>=16 && 
                    atoi(ip[0].c_str())<=172 && atoi(ip[1].c_str())<=31) || 
                   (atoi(ip[0].c_str())>=192 && atoi(ip[1].c_str())>=168 && 
                    atoi(ip[0].c_str())<=192 && atoi(ip[1].c_str())<=168))
                    result[6] += 1;
            }
            else
            {
                result[5] += 1;
            }
        }
        else
        {
            result[5] += 1;
        }
    }
    cout<<result[0]<<" "<<result[1]<<" "<<result[2]<<" "<<result[3]<<" "<<result[4]<<" "<<result[5]<<" "<<result[6]<<endl;
    return 0;
}

发表于 2018-06-18 17:26:01 回复(0)
//完美AC,
思路:
首先必须注意当ip属于某类地址同时属于私有地址都需要进行加1
1)先判断子网掩码是否合法,如果不合法则直接error+=1
思路:说下,我的判断子网掩码的方法与上述不同,既然子网掩码为前面的连续的1,后面为连续的0,
我们可以计算前面2个01串不同的次数,如果为2则说明是正确的,如果超过2,说明不对。这里也正好
不需要判断子网255.255.255.255和0.0.0.0等特殊的子网掩码,在我的方法里这2种特殊子网掩码是不合法的。
2)判断属于哪类地址
3)判断是否是私有地址
import java.util.*;
public class Main_01{
public static void main(String[]args){
   int typeA=0;
   int typeB=0;
   int typeC=0;
   int typeD=0;
   int typeE=0;
   int error=0;
   int privateIp=0;
   Scanner s=new Scanner(System.in);
   while(s.hasNext()){
       String information=s.next();
       String [] info=information.split("~");
       if(info==null||info.length!=2)
           break;
       String ip=info[0];
       String mask=info[1];
       String []ips=ip.split("\\.");
       if(ips==null||ips.length<4)
       {
           error+=1;
         //  System.out.println("out..");
           continue;
       }
       int v=Integer.parseInt(ips[0]);
       
       int two=Integer.parseInt(ips[1]);
       //process mask
       boolean isMask=checkMask(mask);
       if(!isMask){
           error+=1;
           continue;//不进行下面处理
       }
       //处理ip地址
       if(v>=1&&v<=126)
           typeA++;
       else if(v>=128&&v<=191)
           typeB+=1;
       else if(v>=192&&v<=223)
               typeC+=1;
       else if(v>=224&&v<=239)
           typeD+=1;
       else if(v>=240&&v<=255)
           typeE+=1;
       if(v==10||(v==172&&two>=16&&two<=31)||(v==192&&two==168))
           privateIp+=1;
   } //end while
    System.out.println(typeA+" "+typeB+" "+typeC+" "+typeD+" "+typeE+" "+error+" "+privateIp);
}    
public static boolean checkMask(String mask){
    String []masks=mask.split("\\.");
    int v=-1;
    int changeTime=0;//计算相邻数不同的次数
    for(int i=masks.length-1;i>=0;i--){
        int times=0;
        int value=Integer.parseInt(masks[i]);
        while(times<8){
            if((value&1)!=v)
            {
                changeTime+=1;
                v=value&1;
            }
            if(changeTime>=3)
                return false;
            value>>=1;
            times++;
        } //end while
    } //end for
    return changeTime==2?true:false;
}
}

编辑于 2018-04-04 10:37:49 回复(0)

遇到的一些问题:
1.掩码不能是全一,也不能是全零。
2.IP以0或127开头不算错误,只是不用来统计。

import java.util.*;

public class Main {

/*
*子网掩码不为255或者0时,只能是这些情况
*/
private static Set<Integer> set = new HashSet<>(Arrays.asList(128, 192, 224, 240, 248, 252, 254, 255));

/*
*将掩码变成数组,并检查是否有错,如果有错返回null
*/
private static int[] changeMask(String[] s) {
    if (s == null || s.length != 4) {
        return null;
    }

    int[] a = new int[4];
    for (int i = 0; i < 4; ++i) {
        if (s[i] == null || s[i].length() == 0) {
            return null;
        }
        int n = Integer.parseInt(s[i]);
        if (n < 0 || n > 255) {
            return null;
        }
        a[i] = n;
    }


    if (a[0] == 0 || a[3] == 255) {//掩码不能全为1,也不能全是0
        return null;
    }

    int i = 3;
    for (; i >= 0 && a[i] == 0; --i)
        ;
    if (!set.contains(a[i])) {
        return null;
    }

    --i;
    for (; i >= 0 && a[i] == 255; --i)
        ;
    if (i != -1) {
        return null;
    }

    return a;
}

/*
* 将IP变成数组,并检查是否有错,如果有错返回null
*/
private static int[] changeIp(String[] s) {
    if (s == null || s.length != 4) {
        return null;
    }

    int[] a = new int[4];
    for (int i = 0; i < 4; ++i) {
        if (s[i] == null || s[i].length() == 0) {
            return null;
        }
        int n = Integer.parseInt(s[i]);
        if (n < 0 || n > 255) {
            return null;
        }
        a[i] = n;
    }
    return a;
}

public static void main(String[] args) {
    Scanner cin = new Scanner(System.in);
    int a = 0, b = 0, c = 0, d = 0, e = 0, wrong = 0, pri = 0;
    while (cin.hasNext()) {

        String[] s = cin.next().split("~");//将字符串切分为ip和掩码字符串

        String[] ipStr = s[0].split("\\."),
                maskStr = s[1].split("\\.");//将码串按.切分为字符串数组

        int[] ip = changeIp(ipStr);
        int[] mask = changeMask(maskStr);//将码串数组转换为数字数组,并检查两个串的合法性

        if (ip == null || mask == null) {//如果任意一个串不合法,++wrong
            ++wrong;
            continue;
        }

        int first = ip[0];
        int second = ip[1];//主要判断前两个数

        if (first >= 1 && first <= 126) {
            ++a;
            if (first == 10) {
                ++pri;
            }
        } else if (first >= 128 && first <= 191) {
            ++b;
            if (first == 172) {
                if (second >= 16 && second <= 31) {
                    ++pri;
                }
            }
        } else if (first >= 192 && first <= 223) {
            ++c;
            if (first == 192 && second == 168) {
                ++pri;
            }
        } else if (first >= 224 && first <= 239) {
            ++d;
        } else if (first >= 240 && first <= 255) {
            ++e;
        }

    }
    System.out.println(a + " " + b + " " + c + " " + d + " " + e + " " + wrong + " " + pri);
}

}

发表于 2017-08-15 12:58:40 回复(0)
复杂了,正则表达式
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int[] result = new int[7];
        while (in.hasNext()) {
            String[] inputArr = in.nextLine().split("~", -1);
            if (inputArr.length != 2) continue;
            String ip = inputArr[0];
            String subnetMask = inputArr[1];
            // 错误IP地址或错误掩码
            if (!isValidIP(ip, subnetMask)) {
                result[5]++;
                continue;
            }
            if (ip.matches("^10(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")
                    || ip.matches("^172\\.(1[6-9]|2\\d|3[01])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){2}$")
                    || ip.matches("^192\\.168(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){2}$")) {
                // 私有IP check
                result[6]++;
            }
            if (ip.matches("^([1-9]|[1-9]\\d|1[01]\\d|12[0-6])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")) {
                // A类IP
                result[0]++;
            } else if (ip.matches("^(12[89]|1[3-8]\\d|19[01])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")) {
                // B类IP
                result[1]++;
            } else if (ip.matches("^(19[2-9]|2[01]\\d|22[0-3])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")) {
                // C类IP
                result[2]++;
            } else if (ip.matches("^(22[4-9]|23\\d)(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")) {
                // D类IP
                result[3]++;
            } else if (ip.matches("^(24\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")) {
                // E类IP
                result[4]++;
            }
        }
        System.out.println(result[0] + " " + result[1] + " " + result[2] + " "
                + result[3] + " " + result[4] + " " + result[5] + " " + result[6]);
        in.close();
    }
    
    private static boolean isValidIP(String ip, String subnetMask) {
        boolean isValid = false;
        if (ip.matches("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")
                && subnetMask.matches("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$")) {
            String[] arr = subnetMask.split("\\.");
            String tmp = padLeft(Integer.toBinaryString(Integer.parseInt(arr[0], 10)))
                    + padLeft(Integer.toBinaryString(Integer.parseInt(arr[1], 10)))
                    + padLeft(Integer.toBinaryString(Integer.parseInt(arr[2], 10)))
                    + padLeft(Integer.toBinaryString(Integer.parseInt(arr[3], 10)));
            if (tmp.matches("^[1]+[0]+$"))
                isValid = true;
        }
        return isValid;
    }
    private static String padLeft(String str) {
        str = "00000000" + str;
        return str.substring(str.length() - 8);
    }
}

发表于 2017-04-25 09:39:57 回复(0)
package cn.zhangxf0406.chinamobile;
import java.util.*;
import java.util.regex.*;
/**
 * 
 * @author zhangxf0406
 * 识别有效的IP地址和掩码并进行分类统计
 */
public class Demo1120 {
	public static boolean judgeIP(String sIP){
		Pattern pattern = Pattern.compile("^(\\d{1,})\\.(\\d{1,})\\.(\\d{1,})\\.(\\d{1,})$");
		Matcher match = pattern.matcher(sIP);
		if(match.matches()){
			String[] s1 = sIP.split("\\.");
			for(String ss : s1){
				int n = Integer.parseInt(ss);
				if(n < 0 || n > 255)
					return false;
			}
			return true;
 		}else
 			return false;
	}
	
	//掩码的规则:前面为1 ,后面为0
	public static boolean judgeMask(String sMask){
		String [] s1 = sMask.split("\\.");
		StringBuilder sb = new StringBuilder();
		for(String ss :s1){
			String temp = Integer.toBinaryString(Integer.parseInt(ss));
//			int len = temp.length();
			while(temp.length() != 8){
				temp = "0"+temp;
			}
			sb.append(temp);
		}
		String  binaryString = sb.toString();
		int index0 = binaryString.indexOf("0");
		//不能以0开始
		if(index0 == 0)
			return false;
		//不能全是1
		if(binaryString.matches("^1{1,}"))
			return false;
		//前面为1 ,后面为0
		String[] s2 = binaryString.split("0");
		if(s2.length == 1)
			return true;
		return false;
	}
	/*
	 * 私网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
	 */
	public static boolean judgePrivateIP(String ip){
		String[] s1 = ip.split("\\.");
		int a = Integer.parseInt(s1[0]);
		int b = Integer.parseInt(s1[1]);
		int c = Integer.parseInt(s1[2]);
		int d = Integer.parseInt(s1[3]);
		if(a == 10)
			return true;
		if(a == 172){
			if(b >=16 && b <= 31)
				return true;
		}
		if(a == 192 && b == 168)
			return true;
		return false;
	}
	
	public static void main(String[] args) {
		int A = 0;
		int B = 0;
		int C = 0;
		int D = 0;
		int E = 0;
		int errorIpOrMask = 0;
		int privateIp = 0;
		Scanner scanner = new Scanner(System.in);
		while(scanner.hasNext()){
			String str = scanner.next();
			String[] s1 = str.split("~");
			String ip = s1[0];
			String mask = s1[1];
			if(!judgeIP(ip) || !judgeMask(mask)){
				errorIpOrMask++;
//				System.out.println(A+" "+B+" "+C+" "+D+" "+E+" "+errorIpOrMask+" "+privateIp);	
//				System.out.println(errorIpOrMask);
				continue;
			}
			//判断A,B,C,D,E
			String firstStr = ip.substring(0,ip.indexOf("."));
			int num = Integer.parseInt(firstStr);
			if(num >= 1 && num <= 126){
				A++;
			}else if(num >= 128 && num <= 191){
				B++;
			}else if(num >= 192 && num <= 223){
				C++;
			}else if(num >= 224 && num <= 239){
				D++;
			}else if(num >= 240 && num <= 255)
				E++;
			
			//判断私有
			if(judgePrivateIP(ip))
				privateIp++;
			
			System.out.println(A+" "+B+" "+C+" "+D+" "+E+" "+errorIpOrMask+" "+privateIp);	

		}
//		System.out.println(A+" "+B+" "+C+" "+D+" "+E+" "+errorIpOrMask+" "+privateIp);	

		scanner.close();

	}

}


发表于 2017-04-12 13:11:59 回复(0)
思路清晰,一看就懂~~
import java.util.*;

public class Main {
    private static final long[] PRIVATE_IP_RANGE = new long[6];

    static {
        PRIVATE_IP_RANGE[0] = str2ip("10.0.0.0");
        PRIVATE_IP_RANGE[1] = str2ip("10.255.255.255");
        PRIVATE_IP_RANGE[2] = str2ip("172.16.0.0");
        PRIVATE_IP_RANGE[3] = str2ip("172.31.255.255");
        PRIVATE_IP_RANGE[4] = str2ip("192.168.0.0");
        PRIVATE_IP_RANGE[5] = str2ip("192.168.255.255");
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int typeA, typeB, typeC, typeD, typeE, errorIPorMask, privateIP;
        typeA = typeB = typeC = typeD = typeE = errorIPorMask = privateIP = 0;

        while (sc.hasNext()) {
            String[] address = sc.next().split("~");

            if (!isLegalFormat(address[0]) || !isLegalFormat(address[1])) {
                errorIPorMask++;
                continue;
            }

            long ip = str2ip(address[0]);
            long mask = str2ip(address[1]);

            if (!isLegalMask(mask)) {
                errorIPorMask++;
                continue;
            }

            if (isPrivateIP(ip)) privateIP++;

            int head = (int) (ip >> 24);

            if (head >= 1 && head <= 126) typeA++;
            else if (head >= 128 && head <= 191) typeB++;
            else if (head >= 192 && head <= 223) typeC++;
            else if (head >= 224 && head <= 239) typeD++;
            else if (head >= 240 && head <= 255) typeE++;
        }

        System.out.printf("%d %d %d %d %d %d %d%n", typeA, typeB, typeC, typeD, typeE, errorIPorMask, privateIP);
    }

    private static long str2ip(String address) {
        long ip = 0;
        String[] nums = address.split("\\.");
        for (String n : nums) {
            ip <<= 8;
            ip += (long)Integer.parseInt(n);
        }
        return ip;
    }

    private static boolean isLegalFormat(String address) {
        return address.matches("^\\d+\\.\\d+\\.\\d+\\.\\d+$");
    }


    private static boolean isPrivateIP(long ip) {
        return (ip >= PRIVATE_IP_RANGE[0] && ip <= PRIVATE_IP_RANGE[1])
                || (ip >= PRIVATE_IP_RANGE[2] && ip <= PRIVATE_IP_RANGE[3])
                || (ip >= PRIVATE_IP_RANGE[4] && ip <= PRIVATE_IP_RANGE[5]);
    }

    private static boolean isLegalMask(long mask) {
        if (mask == 0 || mask == (1L<<32)-1) return false;
        while ((mask & 1) == 0) mask >>= 1;
        return (mask & (mask + 1)) == 0;
    }
}

发表于 2016-12-21 21:15:40 回复(0)