题目
请解析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;
}
加油!!!!