C++判断ip地址和子网掩码是否有效并统计分类
2020-06-20 本文已影响0人
零岁的我
题目描述
请解析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均为非法
注意:
- 类似于
【0.*.*.*】
和【127.*.*.*】
的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时可以忽略 - 私有IP地址和A,B,C,D,E类地址是不冲突的。
输入描述:
多行字符串。每行一个IP地址和掩码,用~隔开。
输出描述:
统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。
示例1
输入:
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地址的检测与分类,直接错误类加1;
- 类似于【0...】和【127...】的IP地址不用管,直接忽略好了;
- 私有IP地址和A,B,C,D,E类地址不冲突,隐含意思是一个ip地址如果既是A类,又是私有地址,则对应的两类计数都要加1;
- 二进制下子网掩码全是1或者全是0,则该子网掩码看作非法的,这与计算机网络中的介绍有出路,但是还是按照题意走;
1. 解题思路1:全用正则表达式
#include<iostream>
#include<string>
#include<regex>
#include<algorithm>
using namespace std;
int ipa,ipb,ipc,ipd,ipe,error,privateIp;
void isIp(string ip)
{
regex patternA("(?:[1-9]|[1-9][0-9]|1[01][0-9]|12[0-6])(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}");
regex patternB("((12[8-9]|1[3-8][0-9]|19[0-1])(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})");
regex patternC("((19[2-9]|2[0-1][0-9]|22[0-3])(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})");
regex patternD("(22[4-9]|23[0-9])(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}");
regex patternE("(24[0-9]|25[0-5])(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}");
regex patternP("((10\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(172\.(1[6-9]|2[0-9]|3[0-1]))|(192\.168))(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){2}");
smatch res;
bool f=false; //f用来标志是否存在ip地址既不属于ABCDE,也不属于私有ip地址,如果存在,则错误类加1
// A、B、C、D、E是互相冲突的,因此可以使用if...else结构,但是私有ip地址的判断不能用在if...else结构中
if(regex_match(ip,res,patternA)){
++ipa;
f=true;
}
else if(regex_match(ip,res,patternB)){
++ipb;
f=true;
}
else if(regex_match(ip,res,patternC)){
++ipc;
f=true;
}
else if(regex_match(ip,res,patternD)){
++ipd;
f=true;
}
else if(regex_match(ip,res,patternE)){
++ipe;
f=true;
}
if(regex_match(ip,res,patternP)){ //判断是否私有ip地址
++privateIp;
f=true;
}
if(!f){
++error;
}
}
bool isMask(string mask)
{
regex patternM("((255|254|252|248|240|224|192|128)(\.0){3})|(255\.(255|254|252|248|240|224|192|128)(\.0){2})|(255\.255\.(255|254|252|248|240|224|192|128)\.0)|(255\.255\.255\.(254|252|248|240|224|192|128))");
smatch res;
if(regex_match(mask,res,patternM)){
return true;
}
else{
++error;
return false;
}
}
int main(int argc,char **argv)
{
string s;
string ip;
string mask;
while(getline(cin,s)){
int index = s.find("~");
ip=s.substr(0,index);
mask=s.substr(index+1);
string ip1=ip.substr(0,ip.find('.'));
string mask1=mask.substr(0,mask.find('.'));
if(isMask(mask)){
if(ip1!="0" && ip1!="127") isIp(ip);
}
}
cout<<ipa<<" "<<ipb<<" "<<ipc<<" "<<ipd<<" "<<ipe<<" "<<error<<" "<<privateIp<<endl;
return 0;
}
正则表达式居然只能ac 90%,原因是超时,难受!难道正则表达式的处理效率比一般的字符串处理函数效率低吗?这个要怎么测试:(
2. 解题思路2:正则表达式与普通的字符串处理函数结合
#include<iostream>
#include<string>
#include<regex>
using namespace std;
int ipa,ipb,ipc,ipd,ipe,error,privateIp;
bool isMask(string mask)
{
regex patternM("((255|254|252|248|240|224|192|128)(\.0){3})|(255\.(255|254|252|248|240|224|192|128)(\.0){2})|(255\.255\.(255|254|252|248|240|224|192|128)\.0)|(255\.255\.255\.(254|252|248|240|224|192|128))");
smatch res;
if(regex_match(mask,res,patternM)){
return true;
}
else{
++error;
return false;
}
return false;
}
bool isNip(string ip)
{
regex pattern("(0|127)(.)*");
smatch res;
if(regex_match(ip,res,pattern)){
return true;
}
return false;
}
//判断ip地址是否有效
bool isIp(string ip)
{
regex patternIP("((2[0-5][0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(2[0-5][0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)");
smatch res;
if(regex_match(ip,res,patternIP)){
return true;
}
else{
++error;
return false;
}
return true;
}
//分类ip地址并统计各个类别的数量
void ipClass(string ip)
{
int index = ip.find('.');
int ip1=stoi(ip.substr(0,index));
int ip2=stoi(ip.substr(index+1,ip.find('.',index+1)-index-1));
if(ip1>=1 && ip1<=126){
++ipa;
if(ip1==10){
++privateIp;
}
}
else if(ip1>=128 && ip1<=191){
++ipb;
if(ip1==172 &&(ip2>=16 && ip2<=31)){
++privateIp;
}
}
else if(ip1>=192 && ip1<=223){
++ipc;
if(ip1==192 && ip2==168){
++privateIp;
}
}
else if(ip1>=224 && ip1<=239){
++ipd;
}
else if(ip1>=240 && ip1<=255){
++ipe;
}
}
int main(int argc,char **argv)
{
string s;
string ip;
string mask;
while(getline(cin,s)){
int index = s.find('~');
ip = s.substr(0,index);
mask = s.substr(index+1);
// cout<<ip<<" "<<mask<<endl;
if(isMask(mask) && !isNip(ip) &&isIp(ip)){
//对ip分类并统计
ipClass(ip);
}
}
cout<<ipa<<" "<<ipb<<" "<<ipc<<" "<<ipd<<" "<<ipe<<" "<<error<<" "<<privateIp<<endl;
return 0;
}
这个是全ac的。