读入字符串,按'~'进行拆分,如果没有找到'~'则地址非法;拆分成ip和mask后,先对mask进行检查,mask转成一个十进制的数,按位从最右边开始找第一个1,这个1的左边不能出现0;使用sscanf对点分十进制的ip进行拆分,得到a,b,c,d,通过对a、b的判断来对ip地址进行划分。

#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>

using namespace std;
enum addr_type
{
    A_type, /*A类地址*/
    B_type, /*B类地址*/
    C_type, /*C类地址*/
    D_type, /*D类地址*/
    E_type, /*E类地址*/
    I_type, /*非法地址*/
    P_type, /*私有地址*/
    O_type, /*其他地址*/
    MAX_TYPE
};
void check_ip_type(const string& str, addr_type& type, bool& is_p_type)
{
    unsigned long a,b,c,d;
    if(str.find_first_not_of("0123456789.") != str.npos)
    {
        type = I_type;
        return;
    }
    if(sscanf(str.c_str(), "%ld.%ld.%ld.%ld", &a,&b,&c,&d) != 4)
    {
        type = I_type;
        return;
    }
    if(a > 255 || b>255 || c>255 || d>255)
    {
        type = I_type;
        return;
    }
    if(a==0 || a==127)
    {
        type = O_type;
        return;
    }
    if(a >= 1 && a<=126)
    {
        type=A_type;
    }else if(a>=128 && a<=191)
    {
        type=B_type;
    }else if(a>=192 && a<=223)
    {
        type=C_type;
    }else if(a>=224 && a<=239)
    {
        type=D_type;
    }else if(a>=240 && a<=255)
    {
        type=E_type;
    }
    if(a==10 || (a==172 && (b>=16 && b<=31)) || (a==192 && b==168))
    {
       is_p_type = true;
    }
}
bool valid_mask(const string& str)
{
    unsigned long a,b,c,d;
    if(str.find_first_not_of("0123456789.") != str.npos)
        return false;
    if(sscanf(str.c_str(), "%ld.%ld.%ld.%ld", &a,&b,&c,&d) != 4)
        return false;
    if(a==255 && b==255 && c==255 && d==255)
        return false;
    if(a==0 && b==0 && c==0 && d==0)
        return false;
    if(a > 255 || b>255 || c>255 || d>255)
        return false;
    unsigned long mask = (a<<24) | (b << 16) | (c << 8) | d;
    //从最低位的bit位查找为1的bit位,该位的左边不能出现0
    bool found_bit1 = false;
    while(mask)
    {
        if(found_bit1)
        {
            if((mask&1) == 0)
            {
                return false;
            }
        }
        else
        {
            found_bit1 = ((mask&1)==1);
        }
        mask>>=1;
    }
    return true;
}
void fun(int count[], const string& str)
{
    size_t offset = str.find('~');
    if(offset != str.npos)
    {
        string ip = str.substr(0,offset);
        string mask = str.substr(offset+1);
        //检查mask是否非法;
        if(valid_mask(mask))
        {
            addr_type type;
            bool is_p_type = false;
            check_ip_type(ip,type,is_p_type);
            //相应的地址类型增加;
            count[type]++;
            //私有地址增加;
            if(is_p_type)
            {
                count[P_type]++;
            }
        }
        else
        {
            count[I_type]++;
        }
    }
    else
    {
        count[I_type]++;
    }
}
int main()
{
    int count[MAX_TYPE]={0};
    string str;
    while(cin >> str)
        fun(count, str);
    //不输出其他类型的地址(0.*.*.*/127.*.*.*);
    for(int i=0;i<MAX_TYPE-1;i++)
    {
        printf("%d ", count[i]);
    }
    return 0;
}