[编程题]识别有效的IP地址和掩码并进行分类统计

Talk is cheap, show me the code.

一、问题描述

请解析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.0~239.255.255.255;

E类地址240.0.0.0~255.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就是一个非法的掩码)
本题暂时默认以0开头的IP地址是合法的,比如0.1.1.2,是合法地址

输入描述:

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

输出描述:

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

输入例子:

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

二、问题分析

题目有些地方没有讲清楚,害我花了很多时间去揣摩意思。首先要确定ip以0开头和以127开头都是正确的输入,不过不属于任何一类而已,然后判断掩码正确与否时除了必须1都在0前面,还要注意255.255.255.255是错误的掩码。另外还要注意私网ip其实也是ABCDE类中某一类,两类都要加一。

解题方式1:

全部代码按逻辑来,不投机取巧。

#include 
#include 
#include 
#include 
using namespace std;

int main()
{
    int aNum = 0, bNum = 0, cNum = 0, dNum = 0, eNum = 0, errNum = 0, priNum = 0;
    int ip[4] = {0}, code[4] = {0};
    string line;
    while (cin >> line)
    {
        string ipstr, codestr;
        bool ipflag = false, codeflag = false;
        istringstream is(line);
        getline(is, ipstr, '~');
        string s;
        int i = 0;
        istringstream is1(ipstr);
        while (getline(is1, s, '.'))
        {
            if (s == "")
            {
                break;
            } else {
                int temp = atoi(s.c_str());
                if (temp < 0 || temp > 255)
                {
                    break;
                } else {
                    if (i < 4)
                        ip[i] = temp;
                    i++;
                }
            }
        }
        if (i != 4)
        {
            errNum += 1;
            continue;
        } else {
            ipflag = true;
        }
        getline(is, codestr, '~');
        istringstream is2(codestr);
        string s1;
        int j = 0;
        while (getline(is2, s1, '.'))
        {
            int temp = atoi(s1.c_str());
            if (s1 == "")
                break;
            else {
                if (temp < 0 || temp > 255)
                {
                    break;
                } else {
                    bitset<8> bs(temp);
                    int t = -1;
                    for (int i = bs.size() - 1; i >= 0; i--)
                    {
                        if (bs[i] == 0)
                        {
                            t = i;
                            break;
                        }
                    }
                    for (int i = t - 1; i >= 0; i--)
                    {
                        if (bs[i] != 0)
                        {
                            temp = -1;
                            break;
                        }
                    }
                    if (temp == -1)
                        break;
                    else {
                        code[j] = temp;
                        j++;
                    }
                }
            }
        }
        if (j != 4)
        {
            errNum++;
            continue;
        } else {
            j = 0;
            while (j < 4 && code[j] == 255)
            {
                j++;
            }
            for (int i = j + 1; i < 4; i++)
            {
                if (code[i] != 0)
                {
                    j = -1;
                    break;
                }
            }

            if (j == -1 || code[3] == 255)
            {
                errNum++;
                continue;
            } else {
                codeflag = true;
            }
        }
        if (ipflag && codeflag)
        {
            if (ip[0] >= 1 && ip[0] <= 126)
            {
                aNum++;
                if (ip[0] == 10)
                    priNum++;
            } else if (ip[0] >= 128 && ip[0] <= 191) {
                bNum++;
                if (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31)
                    priNum++;
            } else if (ip[0] >= 192 && ip[0] <= 223) {
                cNum++;
                if (ip[0] == 192 && ip[1] == 168)
                    priNum++;
            } else if (ip[0] >= 224 && ip[0] <= 239) {
                dNum++;
            } else if (ip[0] >= 240 && ip[0] <= 255) {
                eNum++;
            }
        }
    }
    cout << aNum << " " << bNum << " " << cNum << " " << dNum << " " << eNum << " " << errNum << " " << priNum << endl;
    return 0;
}

虽然全部逻辑实现,但是逻辑不算直观,思路是先判断输入的ip是否有效,有效则存储在ip数组中,然后判断掩码每个数字是不是符合规范的,每个数字都符合规范就把掩码都存储在code数组中,再判断整个32位掩码是不是符合规范的,这里特别要注意出去255.255.255.255的情况,如果ip和掩码都符合规范,再进行分类,同时属于私网和公网某类的两类都需要计数加一。

解题方式2:

下面这种方式判断掩码是否正确是通过列举出8位的所有可能值一次判断的,虽然很直观,但不是很满意。

#include
#include
#include
#include
using namespace std;

int stringtoint(string str){
    stringstream ss;
    ss<>x;
    return x;
}

vector toint(string str){
    vector res;
    string temp;
    int ele;
    for(int i=0;i res){
    if(res.size()!=4)
        return false;
    if(res[0]==255){
        if(res[1]==255){
            if(res[2]==255){
                if(res[3]==254||res[3]==252||res[3]==248||res[3]==240||res[3]==224||res[3]==192||res[3]==128||res[3]==0){
                    return true;
                }
                else{
                    return false;
                }
            }
            else{
                if(res[2]==254||res[2]==252||res[2]==248||res[2]==240||res[2]==224||res[2]==192||res[2]==128||res[2]==0){
                    if(res[3]==0){
                        return true;
                    }
                    else{
                        return false;
                    }
                }
            }
        }
        else{
            if(res[1]==254||res[1]==252||res[1]==248||res[1]==240||res[1]==224||res[1]==192||res[1]==128||res[1]==0){
                if(res[3]==0&&res[2]==0){
                    return true;
                }
                else{
                     return false;
                    }
             }
        }           
    }
    else{
            if(res[0]==254||res[0]==252||res[0]==248||res[0]==240||res[0]==224||res[0]==192||res[0]==128){
                if(res[3]==0&&res[2]==0&&res[1]==0){
                    return true;
                }
            }
                else{
                     return false;
            }      
    }
    return false;
}

int main(){
    string str;
    int* res=new int[7];
    for(int j=0;j<7;j++)
        res[j]=0;
    while(cin>>str){
         string ipstring;
         string maskstring;
        vector ip,mask;
        int i=0;
        for(;str[i]!='~';i++){
            ipstring.push_back(str[i]);
        }
        i++;
        for(;i=0&&ip[1]<=255&&ip[2]>=0&&ip[2]<=255&&ip[3]>=0&&ip[3]<=255){
                if(ip[0]>=1&&ip[0]<=126){
                    res[0]++;
                    if(ip[0]==10)
                        res[6]++;
                }
                else if(ip[0]>=128&&ip[0]<=191){
                    res[1]++;
                    if(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 32)
                        res[6]++;
                }
                else if(ip[0]>=192&&ip[0]<=223){
                    res[2]++;
                    if(ip[0] == 192 && ip[1] == 168)
                        res[6]++;
                }
                else if(ip[0]>=224&&ip[0]<=239){
                    res[3]++;
                }
                else if(ip[0]>=240&&ip[0]<=255){
                    res[4]++;
                }  
            } 
        }
        else{
                res[5]++;
        }
    }
    cout<

解题方式3:

这种方式分层比较清晰,虽然也是通过列举法来判断掩码,但是代码可读性最强。

#include
#include
#include
using namespace std;

void split(string& str, vector& strs){
    int pos=str.find('.');
    while(pos>=0){
        strs.push_back(str.substr(0, pos));
        str=str.substr(pos+1, str.length()-pos-1);
        pos=str.find('.');
    }
    strs.push_back(str);
}

bool checkNum(string& str){
    if(str.size()==0 || str.size()>3)
        return false;
    for(int i=0; i'9')
            return false;
    }
    int num=atoi(str.c_str());
    if(num>=0 && num<=255)
        return true;
    return false;
}

bool checkIP(vector& segs){
    if(segs.size()!=4)
        return false;
    for(int i=segs.size()-1; i>=0; i--){
        if(!checkNum(segs[i]))
            return false;
    }
    //if(atoi(segs[0])==127)
    //    return false;
    return true;
}

bool checkMask(vector& segs){
    if(segs.size()!=4)
        return false;
    bool start=false;
    for(int i=0; i& ip, vector& counter){
    int n1=atoi(ip[0].c_str());
    int n2=atoi(ip[1].c_str());
    if(n1>=1 && n1<=126){
        if(n1==10)
            counter[6]++;
        counter[0]++;
    }else if(n1>=128 && n1<=191){
        if(n1==172 && n2>=16 && n2<=31)
            counter[6]++;
        counter[1]++;
    }else if(n1>=192 && n1<=223){
        if(n1==192 && n2==168)
            counter[6]++;
        counter[2]++;
    }else if(n1>=224 && n1<=239)
        counter[3]++;
    else if(n1>=240 && n1<=255)
        counter[4]++;
}

int main(){
    vector counter(7, 0);
    int W=0, P=0;
    string str;
    while(cin>>str){
        int pos=str.find('~');
        string ip=str.substr(0, pos);
        string mask=str.substr(pos+1, str.length()-pos-1);
        vector ip_segs, mask_segs;
        split(ip, ip_segs);
        split(mask, mask_segs);
        if(!checkIP(ip_segs) || !checkMask(mask_segs))
            counter[5]++;
        else
            classify(ip_segs, counter);
    }
    cout<

你可能感兴趣的:(nowcoder)