C/C++学习笔记

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均为非法
注意:

  1. 类似于【0.*.*.*】【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时可以忽略
  2. 私有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


题意理解:

  1. 做题过程中发现题目中隐含条件:子网掩码错误的情况下,不用进行ip地址的检测与分类,直接错误类加1;
  2. 类似于【0...】和【127...】的IP地址不用管,直接忽略好了;
  3. 私有IP地址和A,B,C,D,E类地址不冲突,隐含意思是一个ip地址如果既是A类,又是私有地址,则对应的两类计数都要加1;
  4. 二进制下子网掩码全是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的。

上一篇下一篇

猜你喜欢

热点阅读