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

解题思路:
这题重头任务是判断IP地址和掩码输入是否合法,需要检查:
(1)有无其他字符乱入
(2)"."和"~"的数量和相对位置是否正确
(3)数字的个数及相对位置是否正确
(4)每个数字的范围是不是在[0,255]
(5)掩码是否合法(前面是连续的1,然后全是0)
(6)0.0.0.0和255.255.255.255也是非法掩码
IP和掩码下输入合法的情况下,分类就很简单了。

注意问题:
多种不合法输入出现,只算一次不合法
移位操作的结果(整型254<<1是508而不是252,因为整型为32位,1的个数没有减少;char型254<<1是-4而不是252,因为代表有符号数)

难点:

边判断格式合法否边提取子段数字


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

int ip[4];
int mask[4];

bool Valid(string s){
	int dotX=0;	// "."的下标
	int numX=0;	// 数字的下标
	int signX=s.find("~");	//记录"~"的下标
	string subs;	//IP地址记录子段
	int i;
	int num;	//每个子段的数字大小

	if(s.find_first_not_of("0123456789.~")!=string::npos)	//有"0123456789.~"以外的字符,格式错误
		return false;
	if(signX==string::npos)	//没有"~",格式错误
		return false;
	if(s.rfind(".")==s.size()-1)	//如果最后一位是"."
		return false;
	for(i=0;i<7;i++){
		dotX=s.find(".",numX);
		if(dotX-numX==0)		//两个"."之间没有数字,格式错误
			return false;
		if(dotX==string::npos)	//少于6个".",格式错误
			return false;
		if(i==2 && (signX-dotX>4 || signX-dotX<2))
			return false;		//"~"和第三个"."之间不是1~3位数字,格式错误
		if(i==3 && (dotX-signX>4 || dotX-signX<2))
			return false;		//第四个"."和"~"之间不是1~3位数字,格式错误
		if(i==3){				//第三次循环取"."和"~"之间的数
			subs=s.substr(numX,signX-numX);
			numX=signX+1;
		}
		else{
			subs=s.substr(numX,dotX-numX);
			numX=dotX+1;
		}
		num=stod(subs);
		if(num<0 || num>255)	//如果子段数字小于0或大于255,地址或掩码错误
			return false;	
		else{
			if(i<=3)
				ip[i]=num;
			else
				mask[i-4]=num;
		}
	}
	if(i==7){	//取出最后一个数字段(最长为3)
		subs=s.substr(numX,3);	//字符串截止为止,最长3位
		num=stod(subs);
		if(num<0 || num>255)	//如果子段数字小于0或大于255,地址或掩码错误
			return false;
		else
			mask[3]=num;
	}
	
	//判断掩码是否合法
	i=0;
	while(mask[i]==255)
		i++;
	if(i==4)
		return false;	//255.255.255.255是非法掩码	
	int rule=254;	//rule是二进制前面全为1,后面全为0的8bits数
	int d=1;	//每次为2的次方,使rule实现左移效果
	int j;
	for(j=0;j<8;j++){
		if(mask[i]==rule)	//第一个非255的掩码子段是前面全1,后面全0则跳出
			break;
		d=d*2;
		rule-=d;			//向左移位,减少头1,增加尾0
	}
	if(j==8)
		return false;	//掩码子段不是前面全1,后面全0,掩码不合法
	while(i!=3){
		i++;
		if(mask[i]!=0)		//非全1掩码子段后还有非0位,掩码不合法
			return false;
	}
	if(mask[0]==0 && i==3)
		return false;	//0.0.0.0是非法掩码

	return true;
}

int main(){
	string str;
	int ACount=0;
	int BCount=0;
	int CCount=0;
	int DCount=0;
	int ECount=0;
	int errorCount=0;
	int privateCount=0;

	while(getline(cin,str)){
		bool flag;
		flag=Valid(str);
		if(!flag){
			errorCount++;
			continue;
		}
		if(ip[0]>=1 && ip[0]<=126){
			ACount++;
			if(ip[0]==10)
				privateCount++;
		}
		else if(ip[0]>=128 && ip[0]<=191){
			BCount++;
			if(ip[0]==172 && ip[1]>=16 && ip[1]<=31)
				privateCount++;
		}
		else if(ip[0]>=192 && ip[0]<=223){
			CCount++;
			if(ip[0]==192 && ip[1]==168)
				privateCount++;
		}
		else if(ip[0]>=224 && ip[0]<=239)
			DCount++;
		else if(ip[0]>=240 && ip[0]<=255)
			ECount++;
	}
	cout<<ACount<<" "<<BCount<<" "<<CCount<<" "<<DCount<<" "<<ECount<<" "<<errorCount<<" "<<privateCount<<endl;
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值