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

题目
请解析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
输入描述:
多行字符串。每行一个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

解决思路:
1、将IP地址和掩码地址转换成整数进行判断。
2、先判断掩码是否有效,再判断IP地址是否有效,都满足就进行分类统计。
(这里有一个问题,子网掩码的范围没有判断???)

#include <iostream>
#include <vector>
#include <string>
using namespace std;
/*
记录IP地址和掩码
*/
typedef struct {
    string ip;
    string mask;
}IP;
/*
统计信息结构体
*/
typedef struct {
    int AIpCount;
    int BIpCount;
    int CIpCount;
    int DIpCount;
    int EIpCount;
    int ErrIpOrMaskCount;
    int PrivateIpCount;
}Statistics;
/*
将地址的转换成int类型,并记录到数组num中
*/
int addrStringToInt(string addr, vector<int> &num) {
    int i, j, len = addr.size();
    string tmp;
    for (i = 0, j = 0; i < len; i++) {
        if (addr[i] == '.') {
            tmp = addr.substr(j, i - j);
            j = i + 1;
            //处理非法的地址
            if (tmp.empty()) {
                return -1;
            }
            num.push_back(atoi(tmp.c_str()));
        }
    }
    tmp = addr.substr(j, i - j);
    if (tmp.empty()) {
        return -1;
    }
    num.push_back(atoi(tmp.c_str()));
    //保证地址由4个整数组成
    if (num.size() != 4) {
        return -1;
    }
    return 0;
}
void checkIpAddr(string ip, Statistics &sta) {
    vector<int> numOfIp;
    if (addrStringToInt(ip, numOfIp) == -1) {
        sta.ErrIpOrMaskCount++;
        return;
    }
    /*
    A~E类地址后三个整数均要满足位于[0,255]闭区间
    */
    if (numOfIp[1] < 0 || numOfIp[1]>255 || numOfIp[2] < 0 || numOfIp[2] > 255 ||
        numOfIp[3] < 0 || numOfIp[3] > 255) {
        sta.ErrIpOrMaskCount++;
        return;
    }
    //A类地址
    if (numOfIp[0] > 0 && numOfIp[0] < 127) {
        sta.AIpCount++;
        //私网IP
        if (numOfIp[0] == 10) {
            sta.PrivateIpCount++;
        }
    }//B类地址
    else if (numOfIp[0] > 127 && numOfIp[0] <= 191) {
        sta.BIpCount++;
        //私网IP
        if (numOfIp[0] == 172 && numOfIp[1] >= 16 && numOfIp[1] <= 31) {
            sta.PrivateIpCount++;
        }
    }//C类地址
    else if (numOfIp[0] > 191 && numOfIp[0] <= 223) {
        sta.CIpCount++;
        //私网IP
        if (numOfIp[0] == 192 && numOfIp[1] == 168) {
            sta.PrivateIpCount++;
        }
    }//D类地址
    else if (numOfIp[0] > 223 && numOfIp[0] <= 239) {
        sta.DIpCount++;
    }//E类地址
    else if (numOfIp[0] > 239 && numOfIp[0] <= 255) {
        sta.EIpCount++;
    }//非法地址
    else {
        sta.ErrIpOrMaskCount++;
    }
    return;
}
int validMaskAddr(string mask) {
    vector<int> numOfMask;
    int i, j;
    if (addrStringToInt(mask, numOfMask) == -1) {
        return -1;
    }
    /*
    掩码转换成IP地址后,要满足位于[0,255]闭区间
    */
    if (numOfMask[0] < 0 || numOfMask[0] > 255 || 
        numOfMask[1] < 0 || numOfMask[1] > 255 || 
        numOfMask[2] < 0 || numOfMask[2] > 255 ||
        numOfMask[3] < 0 || numOfMask[3] > 255) {
        return -1;
    }
    /*
    掩码地址出现比特0后,保证后续的比特均为0。如果全为255,则直接通过。如果出现0<num<255的数,则判断(num-1)|num == 0xff。如果出现0,则判断是否接下来的数都是0。
    */
    for (i = 0; i < 4; i++) {
        if(numOfMask[i] < 255){
            if (numOfMask[i] > 0 && ((numOfMask[i] - 1) | numOfMask[i]) != 0xFF) {
                return -1;
            }
            break;
        }
    }
    for (j = i+1; j < 4; j++) {
        if (numOfMask[j] != 0) {
            return -1;
        }
    }
    return 0;
}
void getIpAndMask(string s, Statistics &sta) {
    int i;
    int len = s.size();
    IP ip;
    for (i = 0; i < len; i++) {
        if (s[i] == '~') {
            break;
        }
    }
    //提取IP地址和子网掩码
    ip.ip = s.substr(0, i);
    ip.mask = s.substr(i + 1);
    //先判断掩码是否有效
    if(validMaskAddr(ip.mask) == -1){
        sta.ErrIpOrMaskCount++;
        return;
    }
    //再进行IP地址的判断及分类统计
    checkIpAddr(ip.ip, sta);
    return;
}
int main() {
    string ipInfo;
    Statistics sta;
    memset(&sta, 0, sizeof(sta));
    while (cin >> ipInfo){
        getIpAndMask(ipInfo, sta);
    }
    cout << sta.AIpCount << " " << sta.BIpCount << " " << sta.CIpCount 
        << " " << sta.DIpCount << " " << sta.EIpCount<< " " << sta.ErrIpOrMaskCount
        << " " << sta.PrivateIpCount << endl;
    system("pause");
    return 0;
}

加油!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值