首页 > 试题广场 >

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

[编程题]识别有效的IP地址和掩码并进行分类统计
  • 热度指数:331845 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

请解析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.0239.255.255.255;

E类地址从240.0.0.0255.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地址和掩码,用~隔开。

请参考帖子https://www.nowcoder.com/discuss/276处理循环输入的问题。


输出描述:

统计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

说明

10.70.44.68~255.254.255.0的子网掩码非法,19..0.~255.255.255.0的IP地址非法,所以错误IP地址或错误掩码的计数为2;
1.0.0.1~255.0.0.0是无误的A类地址;
192.168.0.2~255.255.255.0是无误的C类地址且是私有IP;
所以最终的结果为1 0 1 0 0 2 1        
示例2

输入

0.201.56.50~255.255.111.255
127.201.56.50~255.255.111.255

输出

0 0 0 0 0 0 0

说明

类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略         
#include <iostream>
#include <vector>
#include <string>
#include <bitset>

using namespace std;
int main()
{
    string str;
    int Anum=0,Bnum=0,Cnum=0,Dnum=0,Enum=0,Ernum=0,Snum=0;
    while(getline(cin,str))
    {
        size_t pos=str.find("~");
        if(pos!=string::npos)
        {
            string a=str.substr(0,pos);
            string b=str.substr(pos+1,str.size()-pos-1);
            vector<string> temp1;
            vector<string> temp2;
            
            size_t pos1=a.find(".");
            while(pos1!=string::npos)
            {
                temp1.push_back(a.substr(0,pos1));
                a=a.substr(pos1+1,a.size()-pos1-1);
                pos1=a.find(".");
            }
            if(!a.empty())
            temp1.push_back(a);
          
            size_t pos2=b.find(".");
            while(pos2!=string::npos)
            {
                temp2.push_back(b.substr(0,pos2));
                b=b.substr(pos2+1,b.size()-pos2-1);
                pos2=b.find(".");
            }
            if(!b.empty())
            temp2.push_back(b);
            
            bool IsNext=true;
            
            if(IsNext)
            {
                string strMask;
                for(int i=0;i<temp2.size();i++)
                {
                    bitset<8> b(stoi(temp2[i]));
                    strMask+=b.to_string();
                }
                size_t pos=strMask.find("01");
                size_t pos1=strMask.find("0");
                size_t pos2=strMask.find("1");
                
                if(pos==string::npos&&!(pos1==string::npos&&pos2!=string::npos)
                   &&!(pos2==string::npos&&pos1!=string::npos))
                {
                    IsNext=true;
                }
                else
                {
                    IsNext=false;
                    Ernum++;
                    continue;
                }
            }
            
            vector<int> t1;
            if(IsNext)
            {
                for(int i=0;i<temp1.size();i++)
                {
                    if(temp1[i].empty())
                    {
                        Ernum++;
                        IsNext=false;
                        break;
                    }
                    else
                    {
                        int value=stoi(temp1[i]);
                        if(i==0&&(value==0||value==127))
                        {
                            IsNext=false;
                            break;
                        }
                        else if(value>255||value<0)
                        {
                            Ernum++;
                            IsNext=false;
                            break;
                        }
                        else
                        {
                            t1.push_back(value);
                        }
                    }
                }
            }
            
            if(IsNext)
            {
                if(t1[0]>=1&&t1[0]<=126)
                {
                    Anum++;
                }
                else if(t1[0]>=128&&t1[0]<=191)
                {
                    Bnum++;
                }
                else if(t1[0]>=192&&t1[0]<=223)
                {
                    Cnum++;
                }
                else if(t1[0]>=224&&t1[0]<=239)
                {
                    Dnum++;
                }
                else if(t1[0]>=240&&t1[0]<=255)
                {
                    Enum++;
                }
                
                if(t1[0]==10)
                {
                    Snum++;
                }
                else if(t1[0]==172&&t1[1]>=16&&t1[1]<=32)
                {
                    Snum++;
                }
                else if(t1[0]==192&&t1[1]==168)
                {
                    Snum++;
                }
            }
        }
    }
    cout<<Anum<<" "<<Bnum<<" "<<Cnum<<" "<<Dnum<<" "<<Enum<<" "<<Ernum<<" "<<Snum;
}

发表于 2021-06-29 03:50:04 回复(0)
注意避坑:最后一个输出的后面不能有空格,否则会报告输出格式存在问题
思路是:将IP地址和子网掩码都存入一个32位的数,然后与规定范围比对
#include <stdio.h>

int main()
{
    unsigned int IP[8] = {-1};
    unsigned int IPType[16] = {0};
    unsigned int SubnetMask[31] = {0xffffffff};
    int Statistics[7] = {0};
    int ErrorFlag = 0;
    int i = 0;
    
    memset(IP,-1,sizeof(unsigned int)*8);
    memset(SubnetMask,0xffffffff,sizeof(unsigned int)*31);
    memset(Statistics,0,sizeof(int)*7);
    
    for(int j=0; j<31; j++)
    {
        SubnetMask[j] = SubnetMask[j]<<(j+1);
    }
    
    IPType[0] = 0x01000000;
    IPType[1] = 0x7effffff;
    IPType[2] = 0x80000000;
    IPType[3] = 0xbfffffff;
    IPType[4] = 0xc0000000;
    IPType[5] = 0xdfffffff;
    IPType[6] = 0xe0000000;
    IPType[7] = 0xf0000000;
    IPType[8] = 0xf0000000;
    IPType[9] = 0xffffffff;
    IPType[10] = 0x0a000000;
    IPType[11] = 0x0affffff;
    IPType[12] = 0xac100000;
    IPType[13] = 0xac1fffff;
    IPType[14] = 0xc0a80000;
    IPType[15] = 0xc0a8ffff;
    
    while(scanf("%d",&IP[i])!=EOF)
    {
        //printf("%d ",IP[i]);
        if(getchar()!='\n')
        {
            i++;
        }
        else
        {
            i = 0;
            for(int j=0; j<8; j++)
            {
                if(IP[j]==-1)
                {
                    Statistics[5]++;
                    ErrorFlag = 1;
                    break;
                }
            }
            if(ErrorFlag == 0)
            {
                IP[0] = (IP[0]<<24)|(IP[1]<<16)|(IP[2]<<8)|(IP[3]<<0);
                IP[4] = (IP[4]<<24)|(IP[5]<<16)|(IP[6]<<8)|(IP[7]<<0);
                if(SubnetMask[31-(__builtin_popcount(IP[4]))]!=IP[4])
                {
                    Statistics[5]++;
                    ErrorFlag = 1;
                }
                else
                {
                    if(IP[0]>=IPType[0] && IP[0]<=IPType[1])
                    {
                        Statistics[0]++;
                    }
                    else if(IP[0]>=IPType[2] && IP[0]<=IPType[3])
                    {
                        Statistics[1]++;
                    }
                    else if(IP[0]>=IPType[4] && IP[0]<=IPType[5])
                    {
                        Statistics[2]++;
                    }
                    else if(IP[0]>=IPType[6] && IP[0]<=IPType[7])
                    {
                        Statistics[3]++;
                    }
                    else if(IP[0]>=IPType[8] && IP[0]<=IPType[9])
                    {
                        Statistics[4]++;
                    }
                    
                    if((IP[0]>=IPType[10] && IP[0]<=IPType[11]) || (IP[0]>=IPType[12] && IP[0]<=IPType[13]) || (IP[0]>=IPType[14] && IP[0]<=IPType[15]) )
                    {
                        Statistics[6]++;
                    }
                }
            }
            
            
           ErrorFlag = 0;
            
            
            //printf("    ");
            memset(IP,-1,sizeof(int)*8);
        }
        
    }
    
    for(int j=0; j<6; j++)
    {
        printf("%d ",Statistics[j]);
    }
    printf("%d",Statistics[6]);
    
    return 0;
}



发表于 2021-06-28 11:06:44 回复(0)
这道题有个坑,输出不能多空格,我拿数组输出的,没想那么多,结果掉坑里了。
#include <iostream>
#include <string>
#include <vector>
#include <sstream>

using namespace std;

constexpr int A = 0,
B = 1, C = 2, D = 3, E = 4, error = 5, privated = 6, other = 7;

void split(string str, char ch, vector<string>& re)
{
    re.clear();
    string temp;
    for (char c : str)
    {
        if (c != ch)
        {
            temp += c;
        }
        else
        {
            re.push_back(temp);
            temp.clear();
        }
    }
    re.push_back(temp);
}

struct IP
{
    unsigned char add[4];
    bool mask;
    unsigned int data()
    {
        unsigned int i = (unsigned int)add[0];
        i <<= 8;
        i += add[1];
        i <<= 8;
        i += add[2];
        i <<= 8;
        i += add[3];
        return i;
    }
    bool load(string s)
    {
        // return false means error
        vector<string> sp;
        split(s, '.', sp);
        stringstream ss;
        unsigned int i = 0;
        for (string& t_str : sp)
        {
            if (i > 4 || t_str.empty())
            {
                return false;
            }
            else
            {
                long long t;
                ss << t_str;
                ss >> t;
                ss.clear();
                if (t > 255 || t < 0)
                {
                    return false;
                }
                else
                {
                    add[i] = (unsigned char)t;
                }
            }
            i++;
        }
        // 判断是否能成为掩码
        // 使用int保存4个uchar
        i = data();
        if(i == 0 || i == -1)
        {
            mask = false;
            return true;
        }
        bool b = false;
        for (int l = 0; l < 32; l++)
        {
            mask = true;
            if (!(i & 1) && !b)
            {
                ;
            }
            else if (!(i & 1) && b)
            {
                mask = false;
                break;
            }
            else if ((i & 1) && !b)
            {
                b = true;
            }
            else if ((i & 1) && b)
            {
                ;
            }
            i >>= 1;
        }
        return true;
    }
};

using Mask = IP;

int ipClsCount(string str, bool& b)
{
    // 先分析ip
    vector<string> ips;
    split(str, '~', ips);
    IP ip;
    Mask mask;
    if ((!mask.load(ips[1]) | !ip.load(ips[0]) ) || !mask.mask)
    {
 //       cout << ips[0] << '\t' << ips[1] << ' ' << mask.mask << endl;
        return error;
    }
    
    // Other?
    if (ip.add[0] == 0 || ip.add[0] == 127)
    {
        return other;
    }
    
    // Private?
    if (ip.add[0] == 10)
    {
        b = true;
    }
    else if (ip.add[0] == 172)
    {
        if (ip.add[1] >= 16 && ip.add[1] <= 31)
        {
            b = true;
        }
        else
        {
            b = false;
        }
    }
    else if (ip.add[0] == 192)
    {
        if (ip.add[1] == 168)
        {
            b = true;
        }
    }
        
    // A B C D E?
    if (ip.add[0] <= 126)
    {
        return A;
    }
    else if (ip.add[0] <= 191)
    {
        return B;
    }
    else if (ip.add[0] <= 223)
    {
        return C;
    }
    else if (ip.add[0] <= 239)
    {
        return D;
    }
    else
    {
        return E;
    }
}

int main()
{
    string str;
    while (getline(cin, str))
    {
        int ipCls[8] = {0};
        do 
        {
            bool isExPrivated = false;
            ipCls[ipClsCount(str, isExPrivated)]++;
            if (isExPrivated)
            {
                ipCls[privated]++;
            }
        } while (getline(cin, str) && str != "");
        
        
        for (int i = 0; i < 6; i++)
        {
            cout << ipCls[i] << ' ';
        }
        cout << ipCls[6];
    }
    
    return 0;
}


发表于 2021-05-12 23:57:32 回复(0)
//常规思路,一步一步拆解判断、检查


#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cmath>

/*
运行时间:5ms
超过35.31%用C++提交的代码
占用内存:400KB
超过79.35%用C++提交的代码
*/

using namespace std;

// 将点分十进制的ip地址转换成 255进制的 long long 整数,用于判断ip处于哪个分类区间
long long A1 = 1 * pow(255,3), A2 = 126 * pow(255,3) + 255 * pow(255,2) + 255 * pow(255,1) + 255;
long long B1 = 128 * pow(255,3), B2 = 191 * pow(255,3) + 255 * pow(255,2) + 255 * pow(255,1) + 255;
long long C1 = 192 * pow(255,3), C2 = 223 * pow(255,3) + 255 * pow(255,2) + 255 * pow(255,1) + 255;
long long D1 = 224 * pow(255,3), D2 = 239 * pow(255,3) + 255 * pow(255,2) + 255 * pow(255,1) + 255;
long long E1 = 240 * pow(255,3), E2 = 255 * pow(255,3) + 255 * pow(255,2) + 255 * pow(255,1) + 255;
        
long long priv1 = 10 * pow(255,3), 
     priv12 = 10 * pow(255,3) + 255 * pow(255,2) + 255 * pow(255,1) + 255;
long long priv2 = 172 * pow(255,3) + 16 * pow(255, 2), 
     priv22 = 172 * pow(255,3) + 31 * pow(255,2) + 255 * pow(255,1) + 255;
long long priv3 = 192* pow(255,3) + 168 * pow(255, 2), 
     priv32 = 192 * pow(255,3) + 168 * pow(255,2) + 255 * pow(255,1) + 255;

//按'.'符号 分割ip 或者 mask
void fillDivideString(vector<string>& divided, string& str) {
    //1. 3个点分,4个数字,所以按 . 来分割ip
    char local_str[str.length()+1];
    memcpy(local_str, str.c_str(), str.length()+1);
    const char* del = ".";
    char* tmp = strtok(local_str, del);
    while(nullptr != tmp) {
        if(string(tmp).length() > 0) {    //tmp可能为空
            divided.push_back(tmp);
        }
        tmp = strtok(nullptr, del);
    }
    return;
}

//题目意思
//如果输入的一行中,Ip或mask是错误的,那么这次的输入行归为 错误IP或错误掩码
//所以,如果掩码错误或者ip错误,两者之一就可以归入,另一个不再检查
//先检查mask或先检查ip都一样
void classifyIpMask(vector<int>& count, string& ip, string& mask) {
    //先检查mask合法性,如果mask非法,那么不再检查ip,
    vector<string> mask_divided;
    bool isvalid = true;    //mask是否合法
    fillDivideString(mask_divided, mask);
    if(mask_divided.size() != 4) {
        count[5]++; //错误掩码 +1
    } 
    else {
        //检查掩码的二进制表示,前面是连续的1,后面全是0
       bool foundZero = false;    //辅助检查是否全0
       bool foundOne = false;    //辅助检查啥否全1
       for(int i = 0; i < mask_divided.size(); i++) {
           int m = stoi(mask_divided[i]);
           int offset = 7;    //注意每个part只有8位,所以最大偏移是 7 
           while(offset >= 0 && isvalid) {
                if((m >> offset) & 1) { //该bit是 1
                    foundOne = true;
                    if(foundZero) {    
                        isvalid = false;
                        break;
                    }
                } else {    //否则 该bit是0
                    if(!foundZero) { 
                        foundZero = true;
                    }
                }
                offset--;
            }
            //违反:前面是连续的1,后面全是0
            if(!isvalid) {
                count[5]++;
                break;
            }
        }
        //违反:全1或者全0
        if(isvalid && (!foundZero || !foundOne)) {
            isvalid = false;
            count[5]++;
        }
    }
    
    //如果前面mask检查好合法,继续检查ip
    if(isvalid) {
        vector<string> ip_divided;
        fillDivideString(ip_divided, ip);
        if(ip_divided.size() != 4) { //不合法
            count[5]++; //错误IP地址 +1
        } else {
            //ip分类
            long long sum = 0;
            for(int i = 0; i < ip_divided.size(); i++) {
                //FIX ME: 实际上这里还需要检查 stoi 的参数是否是数字字符串
                long long n = stoi(ip_divided[i]);
                sum += (n * pow(255, 3-i)); //转成一个255进制的数
            }
            if(A1 <= sum && sum <= A2) {    //A类
                count[0]++;
            } 
            else if(B1 <= sum && sum <= B2) {    //B类
                count[1]++;
            }
            else if(C1 <= sum && sum <= C2) {    //C类
                count[2]++;
            }
            else if(D1 <= sum && sum <= D2) {    //D类
                count[3]++;
            }
            else if(E1 <= sum && sum <= E2) {    //E类
                count[4]++;
            }

            if((priv1 <= sum && sum <= priv12)    //私有IP
               || (priv2 <= sum && sum <= priv22)
               || (priv3 <= sum && sum <= priv32)) {
                count[6]++;
            }
        }
    }
}

int main() {
    string ip_and_mask;
    vector<int> count(7, 0);
    while(cin >> ip_and_mask) {
        int pos = ip_and_mask.find_first_of('~');
        string ip = ip_and_mask.substr(0,pos);
        string mask = ip_and_mask.substr(pos+1);
        classifyIpMask(count, ip, mask);
    }
    for(int i = 0; i < count.size(); i++) {
        cout << count[i];
        if(i < count.size()-1) cout << " ";
    }
    cout << endl;
}

发表于 2021-03-23 00:41:47 回复(0)
终于通过了,遇到了不少坑,一方面是对题目理解的不够,一方面是自己写的错误,最后用在VS上自己把问题调试出来了。个人感觉难点主要在错误IP掩码和非法掩码的判定上。
我的思路:
将每行的数据输入字符串str,通过一些办法拿出其中的八个数字存入数组vv,办法为:left为每个数字的头在字符串中的下标,right每个数字的尾后一位在字符串中的下标
for(int i=left;i<right;i++){//将数字拼成字符串
            stemp+=str[i];
        }
然后通过这段代码拼成字符串,再转换为数字存入数组vv即可。
        temp=stoi(stemp);
        vv.push_back(temp);
判断是否非法或者错误主要有两点,一点是数字为空,导致字符连续的情况,比如,1..0.0~0.0.0.0;这条规则在主函数里直接进行了判定。
if(left==right && right!=str.size()-1){//如果出现连续字符时,为错误IP或掩码
          err++;
          iserr=true;
          break;
        }
一种是非法掩码,全为0或者全为1,还有不满足前面连续1,后面连续0这条规则的掩码,这条规则在函数vld()里实现。此外在vld()函数里还判定了当掩码为合法后是否为不存在的IP地址。前面连续1,后面连续0等价于所有的0都在1的右边,即最右的1的下标位置加上0的数量等于31,代码如下
void vld(vector<int> vv,bool &iserr){
     int zero=0,one=32;
     long long int sum=0;
    if(vv[4]==0 || vv[7]==255){
       err++;
       iserr=true;
       return ;
    }//全0全1直接非法
    for(int i=4;i<8;i++){
      int temp=vv[i];
      sum=(sum<<8)+temp;//将掩码拼在一起
    }
    for(int i=0;i<32;i++){
      if(sum%2==1&&one==32)
        one-=i+1;//最右的1
      if(sum%2==0)
        zero++;//0的数量
      sum=sum/2;
    }
    if((zero+one)!=31){//如果0都在1的右边,则0和1的和为31,否则为非法掩码
       err++;
       iserr=true;
       return ;
    }
    else if(vv[0]==0 || vv[0]==127){//判断是否为无效IP
      iserr=true;
      return;
    }
    return ;
}
全部代码如下,仅供参考。
函数ip()为统计合法IP数量,函数prvip为统计私有IP数量。
iserr为是否为错误IP或者非法掩码的标志位。当iserr为true时,便不在调用其它函数。
#include<iostream>
#include<vector>
using namespace std;
int a=0,b=0,c=0,d=0,e=0,err=0,prv=0;
bool iserr=false;
void ip(int num){
  if(num>=1 && num<=126) a++;
  else if(num>=128 && num<=191) b++;
  else if(num>=192 && num<=223) c++;
  else if(num>=224 && num<=239) d++;
  else if(num>=240 && num<=255) e++;
  return;
}
void prvip(int fir,int sec){
  if(fir==10) prv++;
  else if(fir==172 && sec>=16 && sec<=31) prv++;
  else if(fir==192 && sec==168) prv++;
  return;
}
void vld(vector<int> vv,bool &iserr){
     int zero=0,one=32;
     long long int sum=0;
    if(vv[4]==0 || vv[7]==255){
       err++;
       iserr=true;
       return ;
    }//全0全1直接非法
    for(int i=4;i<8;i++){
      int temp=vv[i];
      sum=(sum<<8)+temp;//将掩码拼在一起
    }
    for(int i=0;i<32;i++){
      if(sum%2==1&&one==32)
        one-=i+1;//最右的1
      if(sum%2==0)
        zero++;//0的数量
      sum=sum/2;
    }
    if((zero+one)!=31){//如果0都在1的右边,则0和1的和为31,否则为非法掩码
       err++;
       iserr=true;
       return ;
    }
    else if(vv[0]==0 || vv[0]==127){//判断是否为无效IP
      iserr=true;
      return;
    }
    return ;
}
int main(){
  int temp;
  int left=0,right;//left为每个数字的头,right为每个数字的尾后一位
  string str,stemp;
  vector<int> vv;
  while(cin>>str)
  {
    for(right=0;right<str.size();right++){
      if(str[right]=='.' || str[right]=='~' || right==str.size()-1){//当right为字符或者为最后一位时读取数据
        if(left==right && right!=str.size()-1){//如果出现连续字符时,为错误IP或掩码
          err++;
          iserr=true;
          break;
        }
        if(right==str.size()-1)//当right为最后一位时,+1则为尾后一位;
            right++;
        for(int i=left;i<right;i++){//将数字拼成字符串
            stemp+=str[i];
        }
        temp=stoi(stemp);
        vv.push_back(temp);
        stemp.clear();
        left=right+1;//更新left
      }
    }
    if(!iserr){
      vld(vv,iserr);
      if(!iserr){
          ip(vv[0]);
          prvip(vv[0],vv[1]);
       }
    }
    str.clear();
    vv.clear();
    left=0;
    iserr=false;
  }
    cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e<<" "<<err<<" "<<prv<<endl;
    return 0;
}




发表于 2021-02-26 11:29:11 回复(0)
#include <stdio.h>
#include <stdlib.h>

int check_netmask_vaild(unsigned int netmask_int)
{
    if( (netmask_int==0) || (netmask_int==0xffffffff) )//掩码错误返回0
        return 0;
    netmask_int = ~netmask_int+1;
    if((netmask_int&(netmask_int-1))==0)//也可以写成if(((~netmask_int)&&(~netmask_int+1))==0)
    {
        return 1;
    }
    return 0;
}


int main()
{
    unsigned int ip[4];
    unsigned int netmask[4];
    int a =0, b = 0, c = 0, d = 0, e = 0, err = 0, pri = 0;
    int ret;
    while(1)
    {
        ret = scanf("%d.%d.%d.%d~%d.%d.%d.%d",&ip[3],&ip[2],&ip[1],&ip[0],&netmask[3],&netmask[2],&netmask[1],&netmask[0]);
        //printf("%d\n",ret);
        /*用ret判断scanf成功输入变量的个数*/
        if(ret==EOF)
        {
            break;
        }
        
        else if(ret<8)//比如示例1的第四行,ip[2]读入失败,怎么判断读入失败呢,用ret记录scanf成功读入的个数
        {  //读入个数小于8,该ip地址是个错误的,不需要判断掩码
           err++;//错误的ip地址和错误的掩码放在一起的
        }
        else
        {
            netmask[0] = (netmask[3]<<24)+(netmask[2]<<16)+(netmask[1]<<8)+netmask[0];//8位写成一个十进制数
           // printf("%u\n",netmask[0]);
            if(check_netmask_vaild( netmask[0])==0)//掩码错误
            {
                err++;
            }
            else//掩码正确,开始判断ip地址
            {
                if (ip[3] >= 1 && ip[3] <= 126) a++;
                else if (ip[3] >= 128 && ip[3] <= 191) b++;
                else if (ip[3] >= 192 && ip[3] <= 223) c++;
                else if (ip[3] >= 224 && ip[3] <= 239) d++;
                else if (ip[3] >= 240 && ip[3] <= 255) e++;//ip[3]=0或者127的被忽略掉了
                if (ip[3] == 10 || (ip[3] == 172 && ip[2] >= 16 && ip[2] <= 31) || (ip[3] == 192 && ip[2] == 168)) pri++;
            }
        }
    }
    
    printf("%d %d %d %d %d %d %d\n", a, b, c, d, e, err, pri);
    
    return 0;
}
发表于 2020-09-20 20:46:58 回复(0)
这个是细节题,把情况讨论清楚就好,代码写起来比较长......
#include<iostream>
#include<vector>
#include<string>

using namespace std;

vector<int> parser(string& s) {
    vector<int> nums;
    int i = 0, j = 0;
    while(j < s.size()) {
        if(s[j]!='.') {
            ++j;
        } else {
            if(i==j) {
                nums.push_back(-1);
            } else {
                nums.push_back(atoi(s.substr(i, j-i).c_str()));
            }
            ++j;
            i = j;
        }
    }
    if(i==j) {
        nums.push_back(-1);
    } else {
        nums.push_back(atoi(s.substr(i, j-i).c_str()));
    }
    return nums;
}

bool isOk(vector<int>& nums) {
    if(nums.size() != 4) return false;
    for(int i=0; i<4; ++i) {
        if(nums[i] < 0 || nums[i] > 255) return false;
    }
    return true;
}

bool isMask(vector<int>& nums) {
    unsigned num = 0;
    for(unsigned n : nums) {
        num <<= 8;
        num |= n;
    }
    if(num == 0) return false;
    unsigned bit = (1<<31);
    while(bit) {
        if((num&bit) == 0) break;
        bit >>= 1;
    }
    if(bit == 0) return false;
    while(bit) {
        if((num&bit) != 0) return false;
        bit >>= 1;
    }
    return true;
}

int main() {
    int A=0, B=0, C=0, D=0, E=0, F=0, G=0;
    string str;
    while(cin >> str) {
        int i=0;
        while(str[i]!='~') ++i;
        string ip = str.substr(0, i);
        string mask = str.substr(i+1, str.size()-i);
        
        vector<int> nums = parser(ip);
        vector<int> masks = parser(mask);
        if(isOk(nums) && isOk(masks) && isMask(masks)) {
            if(nums[0] != 127 && nums[0] != 0) {
                if(nums[0] >= 1 && nums[0] <= 126) {
                    ++A;
                } else if(nums[0] >= 128 && nums[0] <= 191) {
                    ++B;
                } else if(nums[0] >= 192 && nums[0] <= 223) {
                    ++C;
                } else if(nums[0] >= 224 && nums[0] <= 239) {
                    ++D;
                } else if(nums[0] >= 240 && nums[0] <= 255){
                    ++E;
                }
            }
            if(nums[0] == 10) ++G;
            if(nums[0] == 192 && nums[1] == 168) ++G;
            if(nums[0] == 172 && nums[1] >=16 && nums[1] <= 31) ++G;
        } else {
            ++F;
        }
    }

    cout << A <<" "<< B <<" "<< C <<" "<< D <<" "
         << E <<" "<< F <<" "<< G  << endl;
    return 0;
}


编辑于 2020-08-29 21:17:15 回复(0)
位运算,整整齐齐
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>

using namespace std;

uint32_t ip_str2bit(string s) {
    uint32_t tmp = 0;
    int i;
    i= 0;
    uint32_t r = 0;
    while (i < s.length()) {
        if (s[i] == '.') {
            r = (r << 8) + tmp;
            tmp = 0;
        } else {
            tmp = tmp * 10 + (s[i] - '0');
        }
        ++i;
    }
    r = (r << 8) + tmp;
    return r;
}

void classify(string s, int r[]) {
    size_t pos = s.find('~');
    string s1 = s.substr(0, pos);
    string s2 = s.substr(pos + 1, s.length() - pos);
    uint32_t b1 = ip_str2bit(s1);
    uint32_t b2 = ip_str2bit(s2);
    
    /* classify Mask */
    if (b2 == 0x00000000 || b2 == 0xFFFFFFFF) {
        ++r[6];
        return;
    }
    b2 = ~b2;
    if (b2 & (b2 + 1)) {
        ++r[6];
        return;
    }
    
    /* classify IP */
    
    // 0.*.*.* unknown network
    if (!((b1 & 0xFF000000) ^ 0x00000000))
        return;
    // 127.*.*.* unknown network
    if (!((b1 & 0xFF000000) ^ 0x7F000000))
        return;
    
    // 10.*.*.* private network
    if (!((b1 & 0xFF000000) ^ 0x0A000000))
        ++r[7];
    // 172.16.0.0 - 172.31.255.255 private network
    if (!((b1 & 0xFFF00000) ^ 0xAC100000))
        ++r[7];
    // 192.168.*.* private network
    if (!((b1 & 0xFFFF0000) ^ 0xC0A80000))
        ++r[7];
    // Type A
    if (!((b1 & 0x80000000) ^ 0x00000000))
        ++r[1];
    // Type B
    if (!((b1 & 0xC0000000) ^ 0x80000000))
        ++r[2];
    // Type C
    if (!((b1 & 0xE0000000) ^ 0xC0000000))
        ++r[3];
    // Type D
    if (!((b1 & 0xF0000000) ^ 0xE0000000))
        ++r[4];
    // Type E
    if (!((b1 & 0xF0000000) ^ 0xF0000000))
        ++r[5];
}

int main() {
    string s;
    int r[8] = {0};
    while (getline(cin, s)) {
        classify(s, r);
    }
    for (int i = 1; i < 7; ++i) {
        cout << r[i] << ' ';
    }
    cout << r[7] << endl;
    return 0;
}


发表于 2020-08-13 22:37:44 回复(0)

输入利用scanf对格式的识别

n = scanf("%d.%d.%d.%d~%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3],
        &mask[0],&mask[1],&mask[2],&mask[3])) != EOF

返回值n为匹配到的整型数数量,n!=8说明读取错误,那么直接排除,不过要记得使用scanf("%s" , buf)把未读取到的字段清理一下,否则影响下次读取并死锁。当n=EOF=-1的时候,读到数据结尾,退出循环。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum IPCLASS{
    A = 0, B, C, D, E, 
    ERR, PRI
} ipclass;

int main(){

    int classcnt[7] = {0};            // ip分类计数
    int n ;                    // 接收scanf返回值 
    int ip[4] = {0};
    int mask[4] = {0};
    while( (n = scanf("%d.%d.%d.%d~%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3],
        &mask[0],&mask[1],&mask[2],&mask[3])) != EOF ){
        // 1.字段不对
        if( n != 8 ){
                        // 不是ip错了就是mask错了
            ipclass = ERR;classcnt[ipclass] ++; 
            char buf[1024] ; scanf("%s", buf) ;     //清理错误缓存
            continue;
         }

        // 2.掩码是否为连续1与全0组合
        int i = 0;
        int flags = 0;            // 缺0字段标志,之后字段必须全0
        int mask_err = 0;         // 错误标志
        if( (mask[0] == 0 && mask[1] == 0 && mask[2] == 0 && mask[3] == 0) ||
            (mask[0] == 255 && mask[1] == 255 && mask[2] == 255 && mask[3] == 255))
            mask_err = 1;
        else
            for( ; i < 4 ; i ++ ){
                if( flags && mask[i] > 0 ){
                    mask_err = 1 ;  break;
                }
                switch( mask[i] ){
                    case 255 : break;        // 全1全0直接进入下一位判断
                    case 0 : case 254: case 252: case 248: case 240: case 224: case 192: case 128 : // 连1判断
                        flags = 1 ; break;            
                    default : mask_err = 1 ; break;    // 其他情况
                }
            }

        if( mask_err ){
            // 掩码错误
            ipclass = ERR ; classcnt[ipclass] ++ ; continue ;
        }

        // 3.ip判断  1)错误ip 小于0 大于255 , 2)ip分类  , 3)私有ip判断
        // 1)错误ip
        int ip_err = 0 ; 
        for(i=0;i<4;i++){
            if( ip[i] > 255 || ip[i] < 0 ){
                ip_err = 1 ; break ;
            }    
        }
        if ( ip_err ){
            // ip 错误
            ipclass = ERR ; classcnt[ipclass] ++ ; continue ;
        }
        // 2)ip分类
        if (ip[0] >= 1 && ip[0] <= 126)         { ipclass = A ; classcnt[ipclass] ++ ; }
        else if (ip[0] >= 128 && ip[0] <= 191)     { ipclass = B ; classcnt[ipclass] ++ ; }
        else if (ip[0] >= 192 && ip[0] <= 223)     { ipclass = C ; classcnt[ipclass] ++ ; }
        else if (ip[0] >= 224 && ip[0] <= 239)     { ipclass = D ; classcnt[ipclass] ++ ; }
        else if (ip[0] >= 240 && ip[0] <= 255)     { ipclass = E ; classcnt[ipclass] ++ ; }

        // 私有ip
        if (ip[0] == 10 || (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || (ip[0] == 192 && ip[1] == 168)) 
                                                { ipclass = PRI ; classcnt[ipclass] ++ ; }

    }
    printf("%d %d %d %d %d %d %d\n" , classcnt[0] , classcnt[1] , classcnt[2] , 
                            classcnt[3] , classcnt[4] , classcnt[5] , classcnt[6]);
    return 0;
}
编辑于 2020-08-10 18:13:08 回复(0)
#include "iostream"
#include "vector"
#include "algorithm"
#include "string"

using namespace std;

string dec2x(int n, int x)
{
	string ans = "";
	do
	{
		int t = n % x;
		if (t >= 0 && t <= 9)
			ans += t + '0';
		else
			ans += t - 10 + 'a';
		n /= x;
	} while (n != 0);
	reverse(ans.begin(), ans.end());
	return ans;
}

int x2dec(string s, int x)
{
	int ans = 0;
	for (int i = 0; i < s.length(); i++)
	{
		if (s[i] >= '0'&&s[i] <= '9')
			ans = ans*x + s[i] - '0';
		else
		{
			if (s[i] >= 'A'&&s[i] <= 'Z')
				s[i] += 'a' - 'A';
			ans = ans*x + s[i] - 'a' + 10;
		}	
	}
	return ans;
}

int s2i(string s)
{
    int num=0;
    if(s.length()==0)
        return -1;//-1代表空字符串
    for(int i=0;i<s.length();i++)
    {
        if(s[i]>='0'&&s[i]<='9')
            num=num*10+s[i]-'0';
    }
    return num;
}

vector<string> s2n(string s,char c)
{
    int pos=0;
    int nextpos=s.find(c,pos);
    vector<string> v;
    while(nextpos!=-1)
    {
        v.push_back(s.substr(pos,nextpos-pos));
        pos=nextpos+1;
        nextpos=s.find(c,pos);
    }
    v.push_back(s.substr(pos,s.length()-pos));//最后没有字符c时必加
    return v;
}

bool maskcheck(int amask[])
{
    bool flag=false;
    if(amask[0]==255)
    {
            if(amask[1]==255)
            {
                if(amask[2]==255)
                {
                    if(amask[3]==254||amask[3]==252||amask[3]==248\
                       ||amask[3]==240||amask[3]==224||amask[3]==192\
                         ||amask[3]==128||amask[3]==0)
                        flag=true;
                }
                else
                {
                    if(amask[2]==254||amask[2]==252||amask[2]==248\
                       ||amask[2]==240||amask[2]==224||amask[2]==192\
                         ||amask[2]==128||amask[2]==0)
                        if(amask[3]==0)
                            flag=true;
                }
            }
            else
            {
                if(amask[1]==254||amask[1]==252||amask[1]==248\
                           ||amask[1]==240||amask[1]==224||amask[1]==192\
                             ||amask[1]==128||amask[1]==0)
                    if(amask[2]==0&&amask[3]==0)
                                flag=true;
            }
        
        
    }
    else
    {
        if(amask[0]==254||amask[0]==252||amask[0]==248\
           ||amask[0]==240||amask[0]==224||amask[0]==192\
           ||amask[0]==128||amask[0]==0)
            if(amask[1]==0&&amask[2]==0&&amask[3]==0)
                flag=true;
    }
    return flag;
}

bool ipcheck(int aip[])
{
    bool flag=false;
    if(aip[0]>=0&&aip[0]<=255)
        if(aip[1]>=0&&aip[1]<=255)
            if(aip[2]>=0&&aip[2]<=255)
                if(aip[3]>=0&&aip[3]<=255)
                    flag=true;
    return flag;
}

int main()
{
    string s;
    int A=0,B=0,C=0,D=0,E=0,err=0,self=0;
    while(getline(cin,s))
    {
        if(s=="")
            break;
        int pos=s.find('~');
        string ip=s.substr(0,pos);
        string mask=s.substr(pos+1,s.length()-pos-1);
        
        vector<string> vip=s2n(ip,'.');
        vector<string> vmask=s2n(mask,'.');
        
        int aip[4]={0};
        int amask[4]={0};
        
        for(int i=0;i<vmask.size();i++)
        {
            aip[i]=s2i(vip[i]);
            amask[i]=s2i(vmask[i]);
        }
        
        bool maskflag=maskcheck(amask);
        bool ipflag=ipcheck(aip);
        
        if(maskflag && ipflag)
        {
            if(aip[0]>=1&&aip[0]<=126)
            {
                A++;
                if(aip[0]==10)
                    self++;
            }
            
            if(aip[0]>=128&&aip[0]<=191)
            {
                B++;
                if(aip[0]==172&&aip[1]>=16&&aip[1]<=31)
                    self++;
            }
            
            if(aip[0]>=192&&aip[0]<=223)
            {
                C++;
                if(aip[0]==192&&aip[1]==168)
                    self++;
            }
            
            if(aip[0]>=224&&aip[0]<=239)
                D++;
            
            if(aip[0]>=240&&aip[0]<=255)
                E++;
            
            
        }
        else
            err++;
        
    }
    cout<<A<<" "<<B<<" "<<C<<" "<<D<<" "<<E<<" "<<err<<" "<<self<<endl;
}

发表于 2020-06-26 17:06:59 回复(0)
傻瓜式解题法:
#include"iostream"
#include"string"
using namespace std;
int main()
{
    string str;
    int Aip = 0;
    int Bip = 0;
    int Cip = 0;
    int Dip = 0;
    int Eip = 0;
    int Myip = 0;
    int errorip = 0;
    while(cin>>str)
    {
        int len = str.length();
        int num[8] = {0};
        //for(int i=0;i<len;i++)
        //int i=0;

        int flag = 0;
        while(1)
        {
            int i = 0;
            int num1 = 0;
            while(str[i]!='.')
            {
                i++;
                num1++;
            }
            if(num1==0)
            {
                break;
            }
            for(int a=0;a<num1;a++)
            {
                num[0]=num[0]*10+(str[a]-'0');
            }
            int num2 = num1;
            i++;
            num2++;
            while(str[i]!='.')
            {
                i++;
                num2++;
            }
            if(num2==num1+1)
            {
                break;
            }
            for(int b=num1+1;b<num2;b++)
            {
                num[1]=num[1]*10+(str[b]-'0');
            }
            int num3 = num2;
            i++;
            num3++;
            while(str[i]!='.')
            {
                i++;
                num3++;
            }
            if(num3==num2+1)
            {
                break;
            }
            for(int c=num2+1;c<num3;c++)
            {
                num[2]=num[2]*10+(str[c]-'0');
            }
            int num4 = num3;
            i++;
            num4++;
            while(str[i]!='~')
            {
                i++;
                num4++;
            }
            if(num4==num3+1)
            {
                break;
            }
            for(int d=num3+1;d<num4;d++)
            {
                num[3]=num[3]*10+(str[d]-'0');
            }
            //cout<<num[0]<<" "<<num[1]<<" "<<num[2]<<" "<<num[3];
            int num5 = num4;
            i++;
            num5++;
            while(str[i]!='.')
            {
                i++;
                num5++;
            }
            if(num5==num4+1)
            {
                break;
            }
            for(int e=num4+1;e<num5;e++)
            {
                num[4]=num[4]*10+(str[e]-'0');
            }
            int num6 = num5;
            i++;
            num6++;
            while(str[i]!='.')
            {
                i++;
                num6++;
            }
            if(num6==num5+1)
            {
                break;
            }
            for(int f=num5+1;f<num6;f++)
            {
                num[5]=num[5]*10+(str[f]-'0');
            }
            int num7 = num6;
            i++;
            num7++;
            while(str[i]!='.')
            {
                i++;
                num7++;
            }
            if(num7==num6+1)
            {
                break;
            }
            for(int g=num6+1;g<num7;g++)
            {
                num[6]=num[6]*10+(str[g]-'0');
            }
            int num8 = num7;
            i++;
            num8++;
            while(i<len)
            {
                i++;
                num8++;
            }
            if(num8==num7+1)
            {
                break;
            }
            for(int h=num7+1;h<num8;h++)
            {
                num[7]=num[7]*10+(str[h]-'0');
            }
            //cout<<num[0]<<" "<<num[1]<<" "<<num[2]<<" "<<num[3]
                //<<" "<<num[4]<<" "<<num[5]<<" "<<num[6]<<" "<<num[7];
            flag = 1;
            break;
        }
        if(flag == 0)
        {
            errorip++;
            continue;
        }
        
        unsigned int temp = 0;
        for(int j=4;j<8;j++)
        {
            temp=num[j]+(temp<<(8));
        }
        temp = ~temp+1;
        if((temp&(temp-1))!=0)
        {
            errorip++;
            continue;
        }
        if((num[4]==0)||num[7]==255)
        {
            errorip++;
            continue;
        }
        int flag2 = 0;
        if((num[0]>=1)&&(num[0]<=126))
        {
            flag2 = 1;
            Aip++;
        }
        else if((num[0]>=128)&&(num[0]<=191))
        {
            flag2 = 1;
            Bip++;
        }
        else if((num[0]>=192)&&(num[0]<=223))
        {
            flag2 = 1;
            Cip++;
        }
        else if((num[0]>=224)&&(num[0]<=239))
        {
            flag2 = 1;
            Dip++;
        }
        else if((num[0]>=240)&&(num[0]<=255))
        {
            flag2 = 1;
            Eip++;
        }
        
        if((num[0]==10)
           ||((num[0]==172)&&(num[1]>=16)&&(num[1]<=31))
           ||((num[0]==192)&&(num[1]==168)))
        {
            flag2 = 1;
            Myip++;
        }
        if((num[4]==0)||(num[4]==127))
        {
            continue;
        }
    }
    cout<<Aip<<" "<<Bip<<" "<<Cip<<" "<<Dip<<" "<<Eip<<" "<<errorip<<" "<<Myip;
    return 0;
}

编辑于 2020-05-08 22:31:43 回复(0)
错误提示没有输入输出数据的问题该怎么解决?
发表于 2020-05-04 18:06:02 回复(0)
结果对了,不知道思路对不对,大家指点指点
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//IP地址
#define A_ADDR_FROM        0x01000000
#define A_ADDR_TO          0x7EFFFFFF
#define B_ADDR_FROM        0x80000000
#define B_ADDR_TO          0xBFFFFFFF
#define C_ADDR_FROM        0xC0000000
#define C_ADDR_TO          0xDFFFFFFF
#define D_ADDR_FROM        0xE0000000
#define D_ADDR_TO          0xEFFFFFFF
#define E_ADDR_FROM        0xF0000000
#define E_ADDR_TO          0xFFFFFFFF

//私网IP地址
#define PRIVATE_IP1_FROM   0x0A000000
#define PRIVATE_IP1_TO     0x0AFFFFFF
#define PRIVATE_IP2_FROM   0xAC100000
#define PRIVATE_IP2_TO     0xAC1FFFFF
#define PRIVATE_IP3_FROM   0xC0A80000
#define PRIVATE_IP3_TO     0xC0A8FFFF

int main()
{
    char ip[2000][200] = {0};
    
    int b1,b2,b3,b4;
    int m1,m2,m3,m4;
    int count = 0;
    while(1){
        if (scanf("%s",&ip[count][0]) != EOF){
            count++;
        } else {
            break;
        }
    }
        
    int out[7]={0};
    int i,ipValue;
    char* tmp;
    int ipFlg;
    int maskFlg;
    
    for (i=0; i<count; i++){
        
        ipFlg = 0;
        maskFlg = 0;
        
        b1 = b2 = b3 = b4 = -1;
        m1 = m2 = m3 = m4 = -1;
        
        tmp = strtok(ip[i], "~");
        sscanf(tmp,"%d.%d.%d.%d", &b1, &b2, &b3, &b4);

        tmp = strtok(NULL, "~");
        sscanf(tmp,"%d.%d.%d.%d", &m1, &m2, &m3, &m4);
        
        if(b1 == -1 || b2 == -1 || b3 == -1 || b4 == -1 || m1 == -1 || m2 == -1 || m3 == -1 || m4 == -1){
            out[5]++;    //IP地址格式错误
        } else {
            
            ipValue = m1<<24 | m2<<16 | m3<<8 | m4;
            if (ipValue == 0xFFFFFFFF || ipValue == 0x0){
                out[5]++;    //非法掩码
            } else if (((ipValue<<1)|ipValue)!=ipValue) {
                out[5]++;    //非法掩码
            } else{
                ipValue = b1<<24 | b2<<16 | b3<<8 | b4;

                if(ipValue >= PRIVATE_IP1_FROM && ipValue <= PRIVATE_IP1_TO) {
                    out[6]++;    //私有IP1
                } else if (ipValue >= PRIVATE_IP2_FROM && ipValue <= PRIVATE_IP2_TO) {
                    out[6]++;    //私有IP2
                } else if (ipValue >= PRIVATE_IP3_FROM && ipValue <= PRIVATE_IP3_TO) {
                    out[6]++;    //私有IP3
                }

                if(ipValue >= A_ADDR_FROM && ipValue <= A_ADDR_TO) {
                    out[0]++;        // A类地址
                } else if(ipValue >= B_ADDR_FROM && ipValue <= B_ADDR_TO) {
                    out[1]++;        // B类地址
                } else if(ipValue >= C_ADDR_FROM && ipValue <= C_ADDR_TO) {
                    out[2]++;        // C类地址
                } else if(ipValue >= D_ADDR_FROM && ipValue <= D_ADDR_TO) {
                    out[3]++;        // D类地址
                } else if(ipValue >= E_ADDR_FROM && ipValue <= E_ADDR_TO) {
                    out[4]++;        // E类地址
                }
            }
        }
    }
    
    printf("%d %d %d %d %d %d %d\n", out[0],out[1],out[2],out[3],out[4],out[5],out[6]);
    
    return 0;
}

编辑于 2020-04-27 19:10:39 回复(0)
237.143.207.113~255.0.0.0 0.154.70.56~255.0.0.0 47.191.88.206~255.255.0.0 252.117.65.51~255.0.0.0 5.127.233.251~255.255.0.0 105.2.227.18~255.0.0.0 42.243.99.190~255.255.143.0 213.136.4.7~255.0.0.0 18.215.41.233~255.255.255.67 193.53.72.97~255.255.0.0 231.25.34.159~255.255.0.0 62.38.160.21~255.78.255.0 193.7.199.159~255.255.0.0 213.188.214.148~255.0.0.0 123.39.218.193~255.178.0.0 240.246.182.37~255.0.0.0 45.217.35.228~255.0.0.0 62.97.41.64~255.0.0.0 210.175.136.234~255.0.0.0 82.198.156.228~255.0.0.0 243.72.65.231~255.0.0.0 95.73.56.172~255.0.0.0 216.124.139.160~255.255.255.0 158.63.191.33~255.255.255.0 170.230.29.86~255.255.120.255 115.232.165.231~255.255.255.255 232.118.3.82~255.28.35.255 12.226.20.210~255.236.0.0 67.76.187.160~255.255.255.0 53.76.14.193~255.0.0.0 80.237.42.83~255.0.0.0 225.2.60.197~255.6.255.13 165.141.251.150~255.255.0.0 172.75.97.143~255.0.0.0 198.166.79.85~255.255.0.0 228.175.133.241~255.255.0.0 70.176.238.139~255.0.0.0 54.67.162.54~255.45.255.120 38.152.223.23~255.0.0.0 129.152.202.62~255.0.0.0 221.9.212.214~255.0.132.0 153.148.236.124~255.255.255.0 188.36.36.43~255.255.0.0 244.155.142.53~255.255.255.0 246.80.203.40~255.255.0.0 124.112.218.29~255.255.0.0 111.209.161.129~255.255.255.0 35.116.236.164~255.255.255.32 179.94.121.97~255.0.0.0 99.96.129.12~255.255.255.255 50.227.105.219~255.0.0.0 29.242.7.49~255.0.0.0 139.31.65.107~255.255.0.0 72.50.111.118~255.255.255.0 193.242.64.7~255.255.0.0 254.56.183.232~255.255.0.0 12.179.234.92~255.255.255.255 17.95.176.188~255.0.0.0 89.209.212.195~255.255.0.0 132.59.5.10~255.255.0.0 82.157.198.52~255.0.0.0 6.72.161.12~255.252.0.0 47.178.94.149~255.255.0.0 147.243.229.30~255.255.255.0 242.18.226.176~255.0.0.0 187.72.221.156~255.0.0.0 74.136.48.91~255.255.255.0 194.161.244.213~255.0.0.0 176.231.190.78~255.255.0.0 223.164.187.227~255.0.0.0 251.47.51.76~255.132.255.0 90.108.60.242~255.255.255.255 163.170.22.99~255.255.255.0 229.78.165.75~255.255.0.0 54.222.173.56~255.255.0.0 190.90.6.221~255.0.0.0 79.60.73.212~255.0.240.0 198.137.223.142~255.0.0.0 19.220.60.252~255.255.255.255 84.109.38.202~255.255.202.0 189.228.141.30~255.255.0.0 114.9.145.171~255.0.0.0 53.208.55.234~255.255.255.0 160.172.82.18~255.255.255.0 51.56.219.106~255.255.0.0 190.207.66.172~255.255.0.0 230.58.1.224~255.255.0.0 64.150.187.135~255.6.255.255 235.40.32.49~255.255.0.0 73.154.128.199~255.0.0.0 58.120.129.127~255.0.44.0 43.15.83.156~255.220.0.0 41.71.211.168~255.255.255.255 163.90.16.26~255.0.0.0 91.199.55.68~255.255.0.0 148.125.152.107~255.0.0.0 15.158.22.221~255.255.255.255 113.200.126.58~255.0.0.0 222.138.60.69~255.255.0.0 224.109.93.237~255.16.0.0 100.79.107.3~255.0.0.0 28.8.87.106~255.255.0.0 35.6.154.226~255.64.0.0 94.66.198.42~255.255.255.0 138.91.63.51~255.255.255.255 79.163.185.212~255.0.73.0 13.47.62.254~255.255.0.0 0.98.251.80~255.255.0.0 64.202.210.194~255.109.0.0 14.40.186.199~255.0.0.0 40.147.20.10~255.130.255.255 42.96.80.216~255.255.0.0 40.209.106.107~255.0.0.44 1.4.190.37~255.0.0.0 90.84.140.176~255.0.0.0 60.160.75.176~255.0.116.0 224.13.12.33~255.0.0.0 121.183.63.101~255.255.0.0 69.251.16.86~255.255.0.0 189.249.195.152~255.255.0.0 214.195.53.224~255.255.255.0 147.92.127.195~255.20.255.255 91.228.181.229~255.0.0.0 133.132.202.183~255.0.0.194 145.99.161.183~255.0.0.0 146.23.46.148~255.255.255.0 53.169.214.204~255.0.0.0 254.188.234.67~255.0.0.0 45.150.148.129~255.121.0.0 116.50.190.222~255.0.0.0 28.132.153.169~255.0.21.0 142.135.130.154~255.0.0.0 159.142.190.4~255.255.0.50 128.6.204.108~255.255.255.255 169.208.53.137~255.255.0.0 91.87.203.152~255.0.0.0 18.106.204.42~255.0.0.0 135.188.203.11~255.38.255.255 212.143.77.99~255.0.0.0 125.156.175.175~255.0.0.0 16.91.71.194~255.255.0.0 188.93.180.198~255.0.35.0 225.199.61.74~255.0.0.0 208.137.66.197~255.250.0.0 182.59.211.127~255.255.255.255 151.114.181.6~255.255.0.0 137.171.116.236~255.255.255.0 49.16.145.71~255.0.0.0 132.125.51.0~255.0.0.0 65.181.121.61~255.255.0.0 93.67.229.191~255.255.255.255 176.131.218.176~255.43.0.0 116.19.9.54~255.255.0.0 120.2.106.116~255.0.0.0 63.121.49.129~255.0.178.0 101.164.139.247~255.0.0.151 87.240.168.249~255.0.0.0 86.13.245.114~255.0.0.0 166.153.184.220~255.255.0.0 140.192.94.128~255.255.255.0 234.137.5.101~255.0.0.0 14.67.45.3~255.255.255.103 139.22.95.184~255.255.255.0 84.167.82.117~255.255.255.0 146.81.247.172~255.255.255.0 43.61.101.60~255.255.255.37 226.181.198.45~255.0.0.0 86.183.134.176~255.0.110.0 172.187.201.37~255.255.255.0 78.92.195.189~255.255.255.58 49.166.53.50~255.255.255.255 217.49.211.121~255.0.0.0 79.247.26.197~255.0.0.0 41.107.42.174~255.0.0.30 245.215.75.184~255.255.0.0 207.2.79.93~255.0.0.0 137.180.128.248~255.255.0.0 218.131.220.8~255.0.0.0 63.81.15.106~255.255.255.0 117.199.49.82~255.0.0.0 72.32.205.233~255.0.0.0 60.102.39.147~255.229.255.0 141.13.125.188~255.0.205.0 192.70.108.29~255.0.0.0 50.110.229.178~255.255.0.63 168.184.56.244~255.167.255.0 183.229.153.179~255.255.0.0 142.11.227.97~255.255.255.255 128.230.188.51~255.0.0.0 115.115.173.90~255.255.255.0 0.225.159.70~255.255.0.0 148.224.29.42~255.255.0.0 253.60.17.23~255.255.255.0 97.129.31.87~255.0.0.0 145.206.229.167~255.0.0.0 179.178.201.165~255.0.0.0 60.6.47.94~255.255.0.0 97.42.90.152~255.158.255.255 219.59.196.192~255.255.0.0 228.16.173.236~255.255.0.232 238.124.61.67~255.0.0.0 148.223.212.228~255.0.193.0 198.177.212.136~255.255.119.255 67.172.177.72~255.0.0.0 82.54.109.193~255.255.0.0 170.75.209.121~255.0.0.0 241.102.6.161~255.255.255.255 107.164.39.154~255.255.255.255 10.208.59.135~255.255.0.0 160.90.191.172~255.255.0.0 218.92.24.2~255.0.0.0 22.221.180.118~255.0.0.0 136.191.32.169~255.0.203.0 89.29.188.169~255.0.0.0 119.179.89.216~255.255.255.255 117.14.180.194~255.0.0.0 12.152.112.19~255.131.255.0 113.12.58.159~255.255.0.0 216.28.65.9~255.255.0.0 155.57.46.56~255.74.255.0 116.88.236.253~255.0.0.0 62.171.35.217~255.0.0.0 19.13.187.141~255.0.0.0 144.166.52.157~255.5.255.255 234.193.80.85~255.255.0.0 179.181.205.29~255.0.0.0
对应输出应该为:
71 41 21 12 10 68 1
你的输出为:
70 41 21 12 10 69 1
上面是系统给的测试用例
我查了A类地址去掉掩码错误的一共70个如下
47.191.88.206~255.255.0.0
5.127.233.251~255.255.0.0
105.2.227.18~255.0.0.0
45.217.35.228~255.0.0.0
62.97.41.64~255.0.0.0
82.198.156.228~255.0.0.0
95.73.56.172~255.0.0.0
67.76.187.160~255.255.255.0
53.76.14.193~255.0.0.0
80.237.42.83~255.0.0.0
70.176.238.139~255.0.0.0
38.152.223.23~255.0.0.0
124.112.218.29~255.255.0.0
111.209.161.129~255.255.255.0
50.227.105.219~255.0.0.0
29.242.7.49~255.0.0.0
72.50.111.118~255.255.255.0
17.95.176.188~255.0.0.0
89.209.212.195~255.255.0.0
82.157.198.52~255.0.0.0
47.178.94.149~255.255.0.0
74.136.48.91~255.255.255.0
54.222.173.56~255.255.0.0
114.9.145.171~255.0.0.0
53.208.55.234~255.255.255.0
51.56.219.106~255.255.0.0
73.154.128.199~255.0.0.0
91.199.55.68~255.255.0.0
113.200.126.58~255.0.0.0
100.79.107.3~255.0.0.0
28.8.87.106~255.255.0.0
94.66.198.42~255.255.255.0
13.47.62.254~255.255.0.0
14.40.186.199~255.0.0.0
42.96.80.216~255.255.0.0
1.4.190.37~255.0.0.0
90.84.140.176~255.0.0.0
121.183.63.101~255.255.0.0
69.251.16.86~255.255.0.0
91.228.181.229~255.0.0.0
53.169.214.204~255.0.0.0
116.50.190.222~255.0.0.0
91.87.203.152~255.0.0.0
18.106.204.42~255.0.0.0
125.156.175.175~255.0.0.0
16.91.71.194~255.255.0.0
49.16.145.71~255.0.0.0
65.181.121.61~255.255.0.0
116.19.9.54~255.255.0.0
120.2.106.116~255.0.0.0
87.240.168.249~255.0.0.0
86.13.245.114~255.0.0.0
84.167.82.117~255.255.255.0
79.247.26.197~255.0.0.0
63.81.15.106~255.255.255.0
117.199.49.82~255.0.0.0
72.32.205.233~255.0.0.0
115.115.173.90~255.255.255.0
97.129.31.87~255.0.0.0
60.6.47.94~255.255.0.0
67.172.177.72~255.0.0.0
82.54.109.193~255.255.0.0
10.208.59.135~255.255.0.0
22.221.180.118~255.0.0.0
89.29.188.169~255.0.0.0
117.14.180.194~255.0.0.0
113.12.58.159~255.255.0.0
116.88.236.253~255.0.0.0
62.171.35.217~255.0.0.0
19.13.187.141~255.0.0.0
希望有人一起确认下,排除错误测试用例
发表于 2020-04-21 22:00:48 回复(3)

这题是真的挺难的。。。
总结一下思路:
1、读取一行字符串,把字符串拆分为ip地址字符串和子网掩码字符串;
2、把两个字符串都转化为int 型数组,ip[4],mask[4],比如192.168.0.0转化为{192,168,0,0},当遇到特殊的字符串比如19..0.,对应{19,-1,0,-1}
3、

bool maskIsValid(int* ip);

判断子网掩码是否正确,注意255.255.255.255是不合法的子网掩码,子网掩码转化为32位unsigned int Mask,对Mask取反加一,Mask=~Mask +1;Mask二进制中1的个数是1说明是正确的子网掩码
4、若子网掩码正确,判断Ip地址是否正确;
5、ip地址正确再判断IP地址属于那种类别

// recognize_ip.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
int stringToint(const string& s)
{
    if (s.empty() == true)    return -1;
    int res = 0;
    for (int i = 0; i < s.size(); ++i)
    {
        int cur = s[i] - '0';
        res = res * 10 + cur;
    }
    return res;
}
//s1为IP地址类型的字符串
void ipstring_to_arr(int* ip,string& s1)
{
    int start = 0, end = 0;
    for (int count = 0; end < s1.size(); ++end)
    {
        if (s1[end] == '.')
        {
            if (count == 2)    break;
            string str = s1.substr(start, end - start);
            ip[count++] = stringToint(str);
            start = end + 1;
        }
    }
    string str = s1.substr(start, end - start);
    ip[2] = stringToint(str);
    if (end == s1.size())
        str = "";
    else
        str = s1.substr(end + 1);
    ip[3] = stringToint(str);
    /*for (int i=0;i<4 ;++i)
        cout << ip[i] << " ";*/
}
bool maskIsValid(int* ip)
{
    if (ip[0] == 255 && ip[1] == 255 && ip[2] == 255 && ip[3] == 255)
        return false;
    unsigned int Mask = 0;
    for (int i = 0; i < 4; ++i)
    {
        int cur = ip[i];
        if (cur 255)
            return false;
        Mask = (Mask << 8) + cur;
    }
    Mask = ~Mask + 1;//按位取反再加1,正确的子网掩码只剩一个1
    if ((Mask & (Mask - 1)) == 0)
        return true;
    else
        return false;
}
int main()
{
    int result[7] = {0,0,0,0,0,0,0};
    //int T = 4;
    string s;
    //cin >> s;
    while (cin >> s)
    {

        string s1, s2;
        int index = 0;
        bool flag = true;
        for (; index < s.size(); ++index)
        {
            if (s[index] == '~')
                break;
        }
        s1 = s.substr(0, index);
        s2 = s.substr(index + 1);
        int ip[4] = { 0 };
        int mask[4] = { 0 };
        ipstring_to_arr(ip, s1);
        ipstring_to_arr(mask, s2);
        /*cout << endl << "mask:" << endl;
        for (int i : mask)
            cout << i << " ";
        cout << endl;*/
        bool flag_mask = maskIsValid(mask);
        if (flag_mask == false)
            ++result[5];
        //判断ip的子网类型
        else
        {
            for (int i = 0; i < 4; ++i)
            {
                if (ip[i] 255)
                {
                    ++result[5];//错误IP地址
                    flag = false;
                    break;
                } 
            }
            if (flag == true)
            {
                if (ip[0] >= 1 && ip[0] <= 126)
                {
                    ++result[0];//A类地址
                    if (ip[0] == 10)
                        ++result[6];//私有ip
                }
                else if (ip[0] >= 128 && ip[0] <= 191)
                {
                    if (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31)
                        ++result[6];//私有地址
                    ++result[1];//B类地址
                }
                else if (ip[0] >= 192 && ip[0] <= 223)
                {
                    if (ip[0] == 192 && ip[1] == 168)
                        ++result[6];//私有地址
                    ++result[2];//C类地址
                }
                else if (ip[0] >= 224 && ip[0] <= 239)
                    ++result[3];//D类地址
                else if (ip[0] >= 240 && ip[0] <= 255)
                    ++result[4];//E类地址
                //else
                    //++result[5];//错误IP地址
            }
        }
    }
    //std::cout << "输出结果:" << endl;

    cout<<result[0]<<" "<<result[1]<<" "<<result[2]<<" "<<result[3]<<" "<<result[4]<<" "
        <<result[5]<<" "<<result[6]<<endl;
    return 0;
}

编辑于 2020-04-15 11:04:32 回复(0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char str[100];
    int result[7] = {0};
    while(~scanf("%s", str))
    {
        int d1, d2, d3, d4, d11, d22, d33, d44, bin[32] = {0};
        memset(bin, 0, 32);
        if(sscanf(str, "%d.%d.%d.%d~%d.%d.%d.%d", &d11, &d22, &d33, &d44, &d1, &d2, &d3, &d4) == 8)
        {
            if(d1 >= 0 && d1 <= 255 && d2 >= 0 && d2 <= 255 && d3 >= 0 && d3 <= 255 && d4 >= 0 && d4 <= 255)
            {
                if(d1 == d2 && d2 == d3 && d3 == d4 && (d1 == 0 || d1 == 255))
                {
                    //putchar('a');
                    result[5]++;
                    continue;
                }
                else
                {
                    int i = 7;
                    while(d1)
                    {
                        bin[i] = d1 % 2;
                        i--;
                        d1 /= 2;
                    }
                    i = 15;
                    while(d2)
                    {
                        bin[i] = d2 % 2;
                        i--;
                        d2 /= 2;
                    }
                    i = 23;
                    while(d3)
                    {
                        bin[i] = d3 % 2;
                        i--;
                        d3 /= 2;
                    }
                    i = 31;
                    while(d4)
                    {
                        bin[i] = d4 % 2;
                        i--;
                        d4 /= 2;
                    }
                    int loc0, loc1;
                    for(i = 0; i < 32; i++)
                        if(bin[i] == 0)
                        {
                            loc0 = i;
                            break;
                        }
                    for(i = 31; i >= 0; i--)
                        if(bin[i] == 1)
                        {
                            loc1 = i;
                            break;
                        }
                    /********************************************
                    for(int x = 0; x < 32; x++)
                        printf("%d ", bin[x]);
                    putchar(10);
                    printf("loc0 = %d, loc1 = %d\n", loc0, loc1);

                    ********************************************/
                    if(loc0 < loc1)
                    {
                        //putchar('b');
                        result[5]++;
                        continue;
                    }
                    else//mask is legal
                    {
                        if(d11 >= 0 && d11 <= 255 && d22 >= 0 && d22 <= 255 && d33 >= 0 && d33 <= 255 && d44 >= 0 && d44 <= 255)
                        {
                            if(d11 == 0 || d11 == 127)
                                continue;
                            if(d11 >= 1 && d11 <= 126)
                                result[0]++;
                            else if(d11 >= 128 && d11 <= 191)
                                result[1]++;
                            else if(d11 >= 192 && d11 <= 223)
                                result[2]++;
                            else if(d11 >= 224 && d11 <= 239)
                                result[3]++;
                            else if(d11 >= 240 && d11 <= 255)
                                result[4]++;
                            else
                            {
                                //putchar('c');
                                result[5]++;
                                continue;
                            }
                            if(d11 == 10)
                                result[6]++;
                            if(d11 == 172 && d22 >= 16 && d22 <= 31)
                                result[6]++;
                            if(d11 == 192 && d22 == 168)
                                result[6]++;
                        }
                        else
                        {
                            //putchar('d');
                            result[5]++;
                            continue;
                        }
                    }
                }
            }
            else
            {
                //putchar('f');
                result[5]++;
                continue;
            }
        }
        else
        {
            //putchar('g');
            result[5]++;
            continue;
        }
    }
    for(int j = 0; j < 7; j++)
    {
        if(j == 0)
            printf("%d", result[j]);
        else
            printf(" %d", result[j]);
    }
    putchar(10);

    return 0;
}
注释的全是debug的时候加的,人都傻了
编辑于 2020-04-08 16:43:15 回复(0)
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
/*
题目描述
请解析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.*.*.*】的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
*/
//将十进制数转换为2进制数string
string intto2(long val) {
    if (val == 0) {
        return "00000000";
    }
    string str = "";
    int i = 0;
    while (val != 1) {
        char c = (val % 2 == 0 ? '0' : '1');
        str.insert(str.begin(), c);
        val /= 2;
    }
    str.insert(str.begin(), '1');
    int n = 8 - str.length() % 8;
    if (n < 8) {
        for (int i = 1; i <= n; i++) {
            str.insert(str.begin(), '0');
        }
    }
    return str;
}
//将二进制的string转换为10进制数
long binto10(string str) {
    long val = 0;
    for (int i = 0; i < str.length(); i++) {
        if (str[i] == '1') {
            long v = 1;
            for (int j = 1; j <= str.length() - i - 1; j++) {
                v *= 2;
            }
            val += v;
        }
    }
    return val;
}
//将ip地址转换为2进制数string
long ipto10(string ip_str) {
    vector < int > v_ip;
    int index = ip_str.find_first_of('.');
    while (index != -1) {
        string part = ip_str.substr(0, index);
        if (!part.empty()) {
            v_ip.push_back(stoi(part));
        }
        ip_str = ip_str.substr(index + 1);
        index = ip_str.find_first_of('.');
    }
    if (!ip_str.empty()) {
        v_ip.push_back(stoi(ip_str));
    }
    if (v_ip.size() != 4) {
        return -1;
    } else {
        string s = "";
        vector < int > ::iterator it;
        for (it = v_ip.begin(); it != v_ip.end(); it++) {
            s += intto2( * it);
        }
        return binto10(s);
    }
}
//
bool check_mask(string mask) {
    vector < int > v_ip;
    int index = mask.find_first_of('.');
    while (index != -1) {
        string part = mask.substr(0, index);
        v_ip.push_back(stoi(part));
        mask = mask.substr(index + 1);
        index = mask.find_first_of('.');
    }
    v_ip.push_back(stoi(mask));
    if (v_ip.size() != 4) {
        return false;
    } else {
        string binstr = "";
        vector < int > ::iterator it;
        for (it = v_ip.begin(); it != v_ip.end(); it++) {
            binstr += intto2( * it);
        }
        int index = binstr.find_first_of('0');
        string tail = binstr.substr(index + 1);
        if (tail.find('1') != -1) {
            return false;
        } else {
            return true;
        }
    }
}
const long A[] = {
    ipto10("1.0.0.0"),
    ipto10("126.255.255.255")
};
const long B[] = {
    ipto10("128.0.0.0"),
    ipto10("191.255.255.255")
};
const long C[] = {
    ipto10("192.0.0.0"),
    ipto10("223.255.255.255")
};
const long D[] = {
    ipto10("224.0.0.0"),
    ipto10("239.255.255.255")
};
const long E[] = {
    ipto10("240.0.0.0"),
    ipto10("255.255.255.255")
};
const long pri1[] = {
    ipto10("10.0.0.0"),
    ipto10("10.255.255.255")
};
const long pri2[] = {
    ipto10("172.16.0.0"),
    ipto10("172.31.255.255")
};
const long pri3[] = {
    ipto10("192.168.0.0"),
    ipto10("192.168.255.255")
};

// C++11
int main() {
    string str = "";
    vector < string > vs;
    while (getline(cin, str)) {
        vs.push_back(str);
    }
    int nA = 0, nB = 0, nC = 0, nD = 0, nE = 0, nPri = 0, err = 0;
    for (int i = 0; i < vs.size(); i++) {
        str = vs[i];
        int index = str.find_first_of('~');
        string ipstr = str.substr(0, index);
        string maskstr = str.substr(index + 1);
        if (!check_mask(maskstr)) {

            err++;
            continue;
        }
        long ip = ipto10(ipstr);
        if (ip == -1) {
            err++;
        } else {
            if (A[0] < ip && ip < A[1]) {
                nA++;
            } else if (B[0] < ip && ip < B[1]) {
                nB++;
            } else if (C[0] < ip && ip < C[1]) {
                nC++;
            } else if (D[0] < ip && ip < D[1]) {
                nD++;
            } else if (E[0] < ip && ip < E[1]) {
                nE++;
            }
            if ((pri1[0] < ip && ip < pri1[1]) || (pri2[0] < ip && ip < pri2[1]) || (pri3[0] < ip && ip < pri3[1])) {
                nPri++;
            }
        }
    }
    cout << nA << ' ' << nB << ' ' << nC << ' ' << nD << ' ' << nE << ' ' << err << ' ' << nPri << endl;
    return 0;
}

编辑于 2020-03-28 17:40:00 回复(0)
//1 255.255.255.255,0.0.0.0 为非法子网掩码
//2 ip地址是不用考虑大于255的情况,以及127.x.x.x,0.0.0.0 这些忽视数据而不是算错 
//2 当子网掩码错误时,不在判断ip是否有效,错误直接加一, 进行下次循环
//3 当一个ip属于ABCDE类中的一个时候,也属于私有ip时,私有ip和他属于的分类都应该加一
#include <stdio.h>
(737)#include <stdlib.h> 
#include <string.h>

int IsMask(char *str)
{
	int i = 0,mask=0,n,temp;
	temp = atoi(str+i);		//提取掩码的第一部分,保存在高24位 
	mask |= (temp<<24);		 
	while(str[i++]!='.');
	temp = atoi(str + i);	//提取掩码的第二部分,保存在高16位
	mask |= (temp<<16);
	while(str[i++]!='.');	 
	temp = atoi(str + i);	//提取掩码的第三部分,保存在高8位
	mask |= (temp<<8);
	while(str[i++]!='.');	//提取掩码的第四部分, 保存在低8位
	temp = atoi(str + i);
	mask |= (temp<<0);
	if(mask == 0xffffffff || mask == 0) //如果掩码全为0,或者全为1,返回0 ,标示非法 
		return 0;
	for(i=31; i>1; i--)		 //从最高位开始找,若发现有01这种情况即可判定非法 
	{
		if(((mask >> i) & 0x1) ==0 && ((mask>>(i-1)) & 0x1) ==1)
		 return 0;	
	}
	return 1;
}
int main()
{
    int i,n,cnt,num[4];
    char temp[32]={0};	//每次输入的数据,放在temp数组临时保存 
    int class[7]={0};	//用于统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数
    while(scanf("%s",temp) != EOF)
    {
    	if(!IsMask(strchr(temp,'~')+1))		//如果掩码错误,直接错误+1,进行下次的判断 
    	{
	    	class[5]++;
	    	continue;
	    }
    	for(i=0,cnt=0; temp[i] != '~';i++)	//循环查找 
    	{
   			n = atoi(temp+i);
	        if(n == 0 && temp[i] == '0' && cnt == 0) //ip为0.x.x.x的直接忽略 
	        	break;
        	if(n == 0 && temp[i] == '.')		//ip为.x..x等情况说明输入错误 
        	{
	        	class[5]++;
	        	break;
	        }
	        num[cnt++] = n;
	        if(cnt == 4)	//当提取到了ip的4部分数据才判断是哪一类 
			{
				if(num[0] >= 1 && num[0] <= 126 )	//A类地址 
				{
					class[0]++;
					if(num[0] == 10 )			//私网IP 
						class[6]++;
				}
				else if(num[0] >= 128 && num[0] <= 191)	//B类地址 
				{
					class[1]++;
					if(num[0] == 172 && num[1] >= 16 && num[1] <= 31)//私网IP 
						class[6]++;
				}
				else if(num[0] >= 192 && num[0] <= 223) //C类地址 
				{
					class[2]++;
					if(num[0] == 192 && num[1] == 168 ) //私网IP 
						class[6]++;
				}
				else if(num[0] >= 224 && num[0] <= 239) //D类地址 
					class[3]++;
			    else if(num[0] >= 240 && num[0] <= 255) //E类地址 
			    	class[4]++;
			}	
			while(temp[i] != '.' && temp[i] != '~')	//寻找到下一个'.' 
				i++;
			if(temp[i] == '~') break;	//若发现'~',说名已经处理完 
	    }
	    
    }
    for(i=0;i<7;i++) //输出显示,注意输出的最后一位不能有空格 
    	if(i<6)
			printf("%d ",class[i]);
		else
			printf("%d",class[i]);
  	
    return 0;
}

发表于 2020-03-17 17:37:34 回复(0)

这里的思路是一边读入一边统计,每次换行都处理一次,附加代码以便参考

#include 
(849)#include 
#include 
(849)#define ADDR_A_START    0x01000000
#define ADDR_A_END      0X7EFFFFFF
(1210)#define ADDR_B_START    0x80000000
#define ADDR_B_END      0XBFFFFFFF
(1211)#define ADDR_C_START    0xC0000000
#define ADDR_C_END      0XDFFFFFFF
(1212)#define ADDR_D_START    0XE0000000
#define ADDR_D_END      0XEFFFFFFF
(1213)#define ADDR_E_START    0XF0000000
#define ADDR_E_END      0XFFFFFFFF
(1214)#define ADDR_S_START_1  0X0A000000
#define ADDR_S_END_1    0X0AFFFFFF
(1215)#define ADDR_S_START_2  0XAC100000
#define ADDR_S_END_2    0XAC1FFFFF
(1216)#define ADDR_S_START_3  0XC0A80000
#define ADDR_S_END_3    0XC0A8FFFF
unsigned int getHex(unsigned int ip[8],int isIp){
    unsigned int result=0;
    if(isIp){
        for(int i=0;i<4;i++){
                result<<=8;
                result+=ip[i];
            }
    }else{
        for(int i=4;i<8;i++){
                result<<=8;
                result+=ip[i];
            }
    }
    return result;
}
bool checkMark(unsigned int code){
    int counterR=0;
    while (!(code&0x01))//找到第一个1的位置
    {
        code>>=1;
        counterR++;
    }
    if(counterR==0) return false;
    counterR=32-counterR;
    while(counterR--)
    {
        code>>=1;
        if(!(code&0x01)){
            break;
        }
    }
    if(counterR!=0){
       return false;  
    } 
    else{
        return true;
    }
}
int main(){
    int ips[1000][8]={0};
    char in=0,lastIn=0;
    int counter=0,position=0,num=0;
    int wrongSign=0;
    int A=0,B=0,C=0,D=0,E=0,W=0,S=0;
    unsigned int markCode=0,tempIP=0;
    while((in=getchar())!=EOF){
        if('.'==in||'~'==in){//一个数字输入完毕
            if(lastIn>'9'||lastIn<'0'){
                wrongSign=1;
            }
            ips[counter][position]=num;
            position++;
            num=0;
            lastIn=in;
        }else   if('\n'==in){//一行输入完毕
            ips[counter][position]=num;
            if(lastIn>'9'||lastIn<'0'){
                wrongSign=1;
            }
            markCode=getHex(ips[counter],0);
            unsigned int temp1=markCode;
            //检查掩码 
            if(!checkMark(markCode)) {
                wrongSign=1;
            }
            if(wrongSign){
                memset(ips[counter],0,4*sizeof(unsigned int));
                W++;
                wrongSign=0;
            }
            else{
                // printf("Mask->%d.%d.%d.%d\n",ips[counter][4],ips[counter][5],ips[counter][6],ips[counter][7]);
                //分析地址
                tempIP=getHex(ips[counter],1);
                if(tempIP>=ADDR_A_START&&tempIP<=ADDR_A_END)
                    A++;
                if(tempIP>=ADDR_B_START&&tempIP<=ADDR_B_END)
                    B++;
                if(tempIP>=ADDR_C_START&&tempIP<=ADDR_C_END)
                    C++;
                if(tempIP>=ADDR_D_START&&tempIP<=ADDR_D_END)
                    D++;
                if(tempIP>=ADDR_E_START&&tempIP<=ADDR_E_END)
                    E++;
                if(tempIP>=ADDR_S_START_1&&tempIP<=ADDR_S_END_1)
                    S++;
                if(tempIP>=ADDR_S_START_2&&tempIP<=ADDR_S_END_2)
                    S++;
                if(tempIP>=ADDR_S_START_3&&tempIP<=ADDR_S_END_3)
                    S++;                
                //end
                counter++;
            }
            num=0;
            position=0;
            lastIn=in;
            continue;
        }
        else{
            num=num*10+(in-'0');
            lastIn=in;
        }        
    }
    /* for(int i=0;i<counter;i++){
        printf("Valid:%d.%d.%d.%d~%d.%d.%d.%d\n",ips[i][0],ips[i][1],ips[i][2],ips[i][3],ips[i][4],ips[i][5],ips[i][6],ips[i][7]);
    } */
    //开始处理地址
    printf("%d %d %d %d %d %d %d\n",A,B,C,D,E,W,S);
    return 0;
}
发表于 2020-03-02 16:07:14 回复(0)
#include<stdio.h>
#include<string.h>

int main()
{

    int ip_num[8],result[7]={},mask_bin[32],flag1,flag2,flag3,i,j,k,cnt_0,cnt_1;

    while(scanf("%d.%d.%d.%d~%d.%d.%d.%d", &ip_num[0], &ip_num[1], &ip_num[2], &ip_num[3], &ip_num[4], &ip_num[5], &ip_num[6], &ip_num[7]) != EOF)
    {
        flag1 = 0;
        flag2 = 0;
        flag3 = 0;
        cnt_0 = 0;
        cnt_1 = 0;
        j = 0;
        for (i = 0; i < 8; i++)
        {
            if (ip_num[i] < 0 || ip_num[i] > 255)
            {
                result[5]++;
                flag1 = 1;
                break;
            }
        }

            if(flag1 == 0)
            {
                for (i = 4; i < 8;i++)
                {
                    k = 128;
                    if(ip_num[i] == 0)
                    {
                        cnt_0++;
                    }
                    else if(ip_num[i] == 255)
                    {
                        cnt_1++;
                    }
                    //写的十进制转二进制方法,可模块化
                    while(j<=(8*(i-3)-1))
                    {
                        if(ip_num[i] / k)
                        {
                            mask_bin[j] = 1;
                            ip_num[i] = ip_num[i] - k;
                        }
                        else
                        {
                            mask_bin[j] = 0;
                        }
                        k /= 2;
                        j++;
                    }
                }
                if(cnt_0 == 4 || cnt_1 == 4)
                {
                    result[5]++;
                    flag2 = 1;
                }
                if(flag2==0)
                {
                    for (i = 0; i < 31;i++)
                    {
                        if(mask_bin[i+1]>mask_bin[i])
                        {
                            result[5]++;
                            flag3 = 1;
                            break;
                        }
                    }
                }
            }
            if(flag1 == 0 && flag2 == 0 && flag3 == 0)
            {
                if(ip_num[0]>=1&&ip_num[0]<=126)
                    result[0]++;
                else if(ip_num[0]>=128&&ip_num[0]<=191)
                    result[1]++;
                else if(ip_num[0]>=192&&ip_num[0]<=223)
                    result[2]++;
                else if(ip_num[0]>=224&&ip_num[0]<=239)
                    result[3]++;
                else if(ip_num[0]>=240&&ip_num[0]<=255)
                    result[4]++;
                if(ip_num[0]==10 || (ip_num[0]==172&&ip_num[1]>=16&&ip_num[1]<=31) || (ip_num[0]==192 && ip_num[1]==168))
                {
                    result[6]++;
                }
            }
    }

    printf("%d %d %d %d %d %d %d", result[0], result[1], result[2], result[3], result[4], result[5], result[6]);
 

    return 0;
}


发表于 2020-02-17 00:36:06 回复(0)