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

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

https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682

#include <stdio.h>
#include <string.h>
struct IPType
{
    int Anum;
    int Bnum;
    int Cnum;
    int Dnum;
    int Enum;
    int errornum;
    int privatenum;
};
int CalculateType(char typestr[2],int update[7])
{
    for(int i=0;i<2;i++)
    {
        switch (typestr[i])
        {
        case 'A':update[0]=1;break;
        case 'B':update[1]=1;break;
        case 'C':update[2]=1;break;
        case 'D':update[3]=1;break;
        case 'E':update[4]=1;break;
        case 'e':update[5]=1;break;
        case 'p':update[6]=1;break;
        default:
            break;
        }
    }
    
    
    return update[7];
}



char ReturnIPType(int ip[4])
{
    if(ip[0]<=126 )
    {
        if(ip[0]==0) return 'N';
        if(ip[0]==10) return 'p';
        else return 'A';
    }
    else if (ip[0]<=191)
    {
        if(ip[0]==127) return 'N';
        if(ip[0]==172&&ip[1]>=16&&ip[1]<=31) return 'p';
        else return 'B';
    }
    else if (ip[0]<=223)
    {
        if(ip[0]==192&&ip[1]==168) return 'p';
        else return 'C'; 
    }
    else if (ip[0]<=239)
    {
        return 'D';
    }
    else if (ip[0]>239)
    {
        return 'E';
    }
    
    
    return 'N';//N代表忽略
    
}

int IsSubMask(unsigned int mask)
{
    if(mask==0xFFFFFFFF||mask==0x00000000) return 0;
    //0xFFFFFFFF代表全1 
    //假设0xFFFF0000是待测Mask,则~Mask=0x0000FFFF,~Mask+1=0x00010000,此为2^8
    //按照这种方法计算只需要计算(~Mask)&(~Mask+1)==0,就可以知道是从开头连续的1了
    //或者直接判断(Mask-1)|(Mask)==0xFFFFFFFF(e.g:11110000-1=11101111)
    //想法来源CSDN 作者shinezhang86:http://t.csdnimg.cn/DLbN5
    if(((mask-1)|(mask))==0xFFFFFFFF)
    return 1;
    return 0;
}

int main()
{
    char str[666][32];
    int num=-1;
    do {
    num++;
    }while(scanf("%s",&str[num])!=EOF);
    

    struct IPType ipType={0};

    for(int i=0;i<num;i++)//num是总行数,最后一行是回车所以不用取到
    {
        int errsum=ipType.errornum;
        int dotlct[3];
        int dotnum=-1;
        int tildelct=strlen(str[i]);
        char iptype[2]={'U'};
        for(int j=0;j<strlen(str[i]);j++)
        {
             
            if(str[i][j]=='.'&&++dotnum<3) //判断出地址的三个.的位置
            {
                dotlct[dotnum]=j;
                
                //判断.与.相隔需大于0位且小于3位
                if(dotnum>0)
                {
                    if(dotlct[dotnum]-dotlct[dotnum-1]>4||dotlct[dotnum]-dotlct[dotnum-1]<2) 
                    {
                        ipType.errornum++;
                        break;
                    }
                }
                else
                //每个地址第一个数字段需大于0位且小于3位
                {
                    if(j<tildelct?(dotlct[0]>3||dotlct[0]<1):(dotlct[0]-tildelct<2||dotlct[0]-tildelct>4))
                    {
                        ipType.errornum++;
                        break;
                    }
                }
            }
            if(str[i][j]=='~')//先判断出~的位置,记为j,两个地址以~相隔分开判断
            {
                
                if(j-dotlct[2]>4||j-dotlct[2]<2)
                {
                        ipType.errornum++;
                        break;
                }
                //判断子网掩码长度符合要求
                if(strlen(str[i])-j>7&&strlen(str[i])-j<17)
                {
                    
                    int ip[4]={-1,-1,-1,-1};
                    int ip_k=0;//k保存为第几个字段
                    
                    
                        
                    for(int l=0;l<j&&ip_k<4;l=dotlct[ip_k++]+1)//当前数字下标从起始位置dotlct[k-1]+1到dotlct[k]
                    {
                        
                        char tmp[4]={'\0'};//整合保存当前数字以便转换为int
                        for(int m=0;(ip_k<3)?l+m<dotlct[ip_k]:l+m<j;m++)//判断l(初始位置)+m(第几个数字)<下一个.的位置或当是第四个数字段时<~的位置
                        {
                            
                            tmp[m]=str[i][l+m];
                        }

                        //以上得到了一至三个数字的字符串,先转换成int型赋值给ip
                        ip[ip_k]=atoi(tmp);

                        //判断数字属于0~255
                        if((ip[ip_k]>=0)?( (ip[ip_k]<256)?(0):(1) ):(1)) 
                        {
                            ipType.errornum++;
                            break;
                        }
                        
                    }
                        
                    if(ipType.errornum>errsum) break;//识别IP地址有错误后续跳过
                    else 
                    {
                        dotnum=-1;//重置三个.给子网掩码
                        tildelct=j;//记下波浪号的位置
                    }

                    //再此验证IPtype
                    iptype[0]=ReturnIPType(ip);
                    //printf("%c",iptype);
                    //私有地址和类地址不冲突,所以还需要再进行一次
                    if(iptype[0]=='p')
                    {
                        switch (ip[0])
                        {
                        case 10:
                            iptype[1]='A';
                            break;
                        case 172:
                            iptype[1]='B';
                            break;
                        case 192:
                            iptype[1]='C';
                            break;    
                        default:
                            break;
                        }
                    }

                }
                else 
                {
                    ipType.errornum++;
                    break;
                }


                //Ip地址没太大问题的情况来到这里,此时有j=~的位置,dotnum=0,errsum=ipType.errornum
                //当ip识别为可以忽略不记时,直接跳过
                if(iptype[0]=='N') break;


            }

            //这里是不是~且不是.的地方
            if(j==strlen(str[i])-1)//来到最后一位
            {
                if(j+1-dotlct[2]>4||j+1-dotlct[2]<2)
                {
                        ipType.errornum++;
                        break;
                }
                int submask[4]={0,0,0,0};
                unsigned int mask=0;
                for(int sm_k=0;sm_k<4;sm_k++)
                {
                    
                    char tmp[4]={'\0'};
                    
                    int beginloc=(sm_k>0)?(dotlct[sm_k-1]+1):(tildelct+1);
                    //根据sm_k是第几个数字字段进行自增赋值
                    for(int l=beginloc;(sm_k<3)?(l<dotlct[sm_k]):(l<=j);l++)
                    {
                        tmp[l-beginloc]=str[i][l];
                    }
                    submask[sm_k]=atoi(tmp);
                    //判断数字属于0~255
                    if((submask[sm_k]<0) && (submask[sm_k]>255)) 
                    {
                        ipType.errornum++;
                        break;
                    }
                    //利用位运算合并成一个数,传入识别是否从头连续1的函数
                    else
                    {
                        mask=(mask<<8)+submask[sm_k];
                    }
                    if(sm_k==3) 
                    {
                        if(!IsSubMask(mask)) 
                        {
                            ipType.errornum++;
                            break;
                        }
                    }
                }

                if(ipType.errornum>errsum) break;//识别IP地址有错误后续跳过
                else 
                {
                    //传入之前IP地址返回的字符,识别并计入到结构体中
                    //printf("correct IP and Mask\n");
                    int update[7]={0};
                    update[7]=CalculateType(iptype,update);
                    ipType.Anum+=update[0];
                    ipType.Bnum+=update[1];
                    ipType.Cnum+=update[2];
                    ipType.Dnum+=update[3];
                    ipType.Enum+=update[4];
                    ipType.errornum+=update[5];
                    ipType.privatenum+=update[6];
                    
                }

            }
        }
    }
    


    printf("%d %d %d %d %d %d %d",ipType.Anum,ipType.Bnum,ipType.Cnum,ipType.Dnum,ipType.Enum,ipType.errornum,ipType.privatenum);
    return 0;
}

写了快300行,真的是屎山代码了==

全部评论

相关推荐

10-21 23:48
蚌埠坦克学院
csgq:可能没hc了 昨天一面完秒挂
点赞 评论 收藏
分享
牛客101244697号:这个衣服和发型不去投偶像练习生?
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务