列表

详情


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

描述

请解析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地址,计数时请忽略

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C 解法, 执行用时: 2ms, 内存消耗: 288KB, 提交时间: 2022-07-11

#include <stdio.h>

int main(void)
{
    char str[50];
    int illegal_f;
    int len,i,tmp_i,ip_i,j;
    int ymtmp;
    int A=0,B=0,C=0,D=0,E=0,illegal=0,P=0;
    while(fgets(str,50,stdin)!=NULL){
        int ip[8]={0};
        len=strlen(str)-1;
        str[len]=0;
        illegal_f=0;
        for(i=0,tmp_i=0,ip_i=0;i<len;i++){
            if(('.'==str[i])||('~'==str[i])||(len-1==i)){
                if(len-1==i){
                    i++;
                }
                if((3<i-tmp_i)||(i==tmp_i)){
                    illegal_f=1;
                    break;
                }
                else{
                    for(j=tmp_i;j<i;j++){
                        ip[ip_i]=ip[ip_i]*10+(int)(str[j]-'0');
                    }
                    if((255<ip[ip_i])||(0>ip[ip_i])){
                        illegal_f=1;
                        break;
                    }
                    if(7>ip_i){
                        ip_i++;
                    }
                }
                tmp_i=i+1;
            }
        }

//+++++++++++++掩码合法性确认++++++++++++++++++++++++++++++++++++++
        if(0==illegal_f){                //如果已判断为非法IP,则不需要再判断掩码的合法性了。
            if((0==ip[4])&&(0==ip[5])&&(0==ip[6])&&(0==ip[7])){        //掩码全0:非法。
                illegal_f=1;
            }
            else if((255==ip[4])&&(255==ip[5])&&(255==ip[6])&&(255==ip[7])){//掩码全255:非法。
                illegal_f=1;
            }
            else{
                ymtmp=0;
                for(i=7;3<i;i--){
                    for(ip_i=0;8>ip_i;ip_i++,ip[i]/=2){
                        if(0!=ymtmp){
                            if(0==ip[i]%2){
                                illegal_f=1;
                                break;
                            }
                        }
                        else{
                            ymtmp=ip[i]%2;
                        }
                    }
                    if(0!=illegal_f){
                        break;
                    }
                }
            }
        }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//+++++++++++IP类型统计+++++++++++++++++++++++++++++++++++++++++
        if((0!=ip[0])&&(127!=ip[0])){
            if(0!=illegal_f){                            //非法IP
                illegal++;
            }
            else if((1<=ip[0])&&(126>=ip[0])){            //A类
                A++;
                if(10==ip[0]){                       //私有
                    P++;
                }
            }
            else if((128<=ip[0])&&(191>=ip[0])){    //B类
                B++;
                if(172==ip[0]){                     //私有
                    if((16<=ip[1])&&(31>=ip[1])){
                        P++;
                    }
                }
            }
            else if((192<=ip[0])&&(223>=ip[0])){    //C类
                C++;
                if(192==ip[0]){                     //私有
                    if(168==ip[1]){
                        P++;
                    }
                }
            }
            else if((224<=ip[0])&&(239>=ip[0])){    //D类
                D++;
            }
            else if((240<=ip[0])&&(255>=ip[0])){      //E类
                E++;
            }
        }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    }
    printf("%d %d %d %d %d %d %d",A,B,C,D,E,illegal,P);
    return 0;
}

C 解法, 执行用时: 2ms, 内存消耗: 288KB, 提交时间: 2021-10-08

#include <stdio.h>
#include <string.h>
#include <ctype.h>
char repeat_code(char *s, int *record)
{
    if( !s ) return 0;
    
    int len = strlen(s), i = 0, j = 0, val = 0, idx = 0;
    while(i < len)
    {
        if( isdigit( s[i] ) ){
            val = val*10 + s[i]-'0';
        }
        else if(s[i] == '.'){
            if(j==i || idx==3 || i+1==len || val>255) return 0;
            record[ idx++ ] = val;
            val = 0;   j = i+1;
        }
        else return 0;
        ++i;
    }
    if(idx!=3 || val>255) return 0;
    record[3] = val;
    return 1;
}
char judge_mask(int *mask)
{
    unsigned val = 0;
    for(int i=0; i<4; ++i)
        val |= mask[i]<<(3-i)*8;
    return !(!val || val==0xFFFFFFFF || (val|val-1)!=0xFFFFFFFF);
}
int main(void)
{
    int ip[4], mask[4], cnt[5] = {0}, Err_cnt = 0, private_cnt = 0;
    memset(ip, -1, 4*sizeof(int));
    memset(mask, -1, 4*sizeof(int));
    char s[88];
    while(scanf("%s", s) != EOF)
    {
        int idx = 0;
        while(s[idx] && s[idx]!='~')
            ++idx;
        if( s[idx] ){
            s[idx] = '\0';
        }
        else{
            ++Err_cnt;   goto rpt;
        }
        char ip_flag = repeat_code(s, ip);
        char mask_flag = repeat_code(s+idx+1, mask);
        if(!ip[0] || ip[0]==127) goto rpt;
        if(!ip_flag || !mask_flag || !judge_mask(mask)){
            ++Err_cnt;   goto rpt;
        }
        
        if(ip[0] < 127){
            ++cnt[0];
            if(ip[0] == 10) ++private_cnt;
        }
        else if(ip[0] < 192){
            ++cnt[1];
            if(ip[0]==172 && ip[1]>=16 && ip[1]<=31) ++private_cnt;
        }
        else if(ip[0] < 224){
            ++cnt[2];
            if(ip[0]==192 && ip[1]==168) ++private_cnt;
        }
        else if(ip[0] < 240) ++cnt[3];
        else ++cnt[4];
        
rpt:    memset(ip, -1, 4*sizeof(int));
        memset(mask, -1, 4*sizeof(int));
    }
    
    printf("%d %d %d %d %d %d %d\n", cnt[0], cnt[1], cnt[2], cnt[3], cnt[4], Err_cnt, private_cnt);
    return 0;
}

上一题