华为机试HJ18:识别有效的IP地址和掩码并进行分类统计

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

题目描述:

请解析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就是一个非法的掩码)

注意二进制下全是1或者全是0均为非法

注意:

1. 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时可以忽略

2. 私有IP地址和A,B,C,D,E类地址是不冲突的

输入描述:

多行字符串。每行一个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和mask是不是有效的,如果无效则错误+1,若有效再分类,注意私有的也可能同时属于ABCDE;dec2binary函数和matlab里一样,将十进制转化为2进制的;子网掩码里如果出现了0,后面再出现1就认为是错误的。

测试代码采用了牛客网西南交大的一个大佬,昵称为:大 郅,写的逻辑也是非常清楚,比我写的好,所以推广分享给大家~

测试代码:

#include <iostream>
#include <string>
#include <vector>
#include <list>
using namespace std;

// 初步判断输入的点十分进制表示法是否正确
bool isValid(const string& str, vector<int> & data)
{
	for(int i=0; i<str.size(); ++i)
	{
		int j = i;
		for(; j<=str.size(); ++j)
			if(str[j] == '.' || j == str.size())
			{
				string number(str.begin()+i, str.begin()+j);
				if(number.empty())
					return false;
				int num = atoi(number.c_str());
				data.push_back(num);
				break;
			}
		i = j;
	}

	if(data.size() != 4)
		return false;

	for(int i=0; i<data.size(); ++i)
		if(data[i]<0 || data[i]>255)
			return false;

	return true;
}

// 判断IP地址是否正确
bool ipValidHandle(const string& ip, vector<int> & data)
{
	return isValid(ip, data); }

// 将整形转化为二进制表示,只取低8位 128 --> 10000000
void dec2binary(int num, list<char> & mask_binary)
{
	for(int i=0; i<8; ++i)
	{
		mask_binary.push_front((num & 1)+'0');
		num = num>>1;
	}
}

// 判断子网掩码是否正确
bool maskValidHandle(const string& mask)
{
	vector<int> res;
	list<char> mask_binary;
	if(!isValid(mask, res))
		return false;
	
	// 将子网掩码转化为二进制的字符串表示
	// 255.255.255.0 --> 1111111111111111111111110000000
	for(int i=res.size()-1; i>=0; --i)
		dec2binary(res[i], mask_binary);
	
	bool find1 = false, find0 = false;
	for(list<char>::iterator it=mask_binary.begin(); it!=mask_binary.end(); ++it)
		if(!find1 && *it == '1')
			find1 = true;
		else if(!find0 && *it== '0')
			find0 = true;
		else if(find0 && *it== '1')
			return false;

	if(find0 && find1)
		return true;
	return false;
}

int main()
{
	string line;
	int ip_A = 0, ip_B = 0, ip_C = 0, ip_D = 0;
	int ip_E = 0, ip_Err = 0, ip_private = 0;

	while(getline(cin, line))
	{
		for(int i=0; i<line.size(); ++i)
			if(line[i] == '~')
			{
				string ip(line.begin(), line.begin()+i);
				string mask(line.begin()+i+1, line.end());
				vector<int> data;
				if(ipValidHandle(ip, data) && maskValidHandle(mask))
				{
					if(data[0] >=1 && data[0] <= 126)
					{
						if(data[0] == 10)
							ip_private++;
						ip_A++;
					}
					else if(data[0] >=128 && data[0]<=191 )
					{
						if(data[0] == 172 && (data[1]>=16 && data[1]<=31))
							ip_private++;
						ip_B++;
					}
					else if(data[0] >=192 && data[0] <= 223)
					{
						if(data[0] == 192 && data[1]==168)
							ip_private++;
						ip_C++;
					}
					else if(data[0] >=224 && data[0] <= 239)
						ip_D++;
					else if(data[0] >=240 && data[0] <= 255)
						ip_E++;
				}
				else 
					++ip_Err;
				break;
			}
	}

	cout<<ip_A<<" "<<ip_B<<" "<<ip_C<<" "<<ip_D<<" "<<ip_E<<" "<<ip_Err<<" "<<ip_private<<endl;

	return 0;
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翟天保Steven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值