首页 > 其他分享 >华为机试HJ18 识别有效的IP地址和掩码并进行分类统计

华为机试HJ18 识别有效的IP地址和掩码并进行分类统计

时间:2024-11-03 16:50:43浏览次数:3  
标签:int HJ18 ++ 255.255 地址 && 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.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地址和掩码,用~隔开。

请参考帖子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地址,计数时请忽略        

一、问题分析

1.解析IP地址和对应的掩码,进行分类识别。

2.按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。

3.一共有五类IP地址

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

4.子网掩码为二进制下前面是连续的1,然后全是0。

举例说明255.255.255.32是一个非法的掩码

因为它的二进制是11111111.11111111.1111111.00100000

不是全都连续

5.题目还提及了二进制下全是1或者全是0均为非法子网掩码

也就是说255.255.255.255和0.0.0.0是非法子网掩码

6.提及了两个注意的点

①类似于0.*.*.*和127.*.*.*的IP地址不属于上述输入的任何一类,也不属于不合法ip地址,计数时忽略

②私有IP地址和A,B,C,D,E类地址是不冲突的(也就是说一个地址他可以是A类私有也可是是A类公有)

7.输入描述:多行字符串,每行一个IP地址和掩码,用~隔开。

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

8.输出描述:统计A、B、C、D、E、错误IP地址或错误掩码、私有的IP的个数,之间以空格隔开。

9.通过读题我们的到题目大概的意思是输入一些IP和掩码,让我们来统计这些

IP和掩码的组合中A类地址,B类地址,C类地址,D类地址,E类地址,

错误的IP地址或错误掩码

以及私有的IP的个数

这些数字之间以空格隔开

10.我们来看一下示例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
这个输入输入了四条IP和掩码组合

第一条是A类地址,但是掩码前面的部分不是连续的1,所以这是一个不合法的掩码(单独归类)

第二条是一个A类地址,且掩码前面8位都是1,所以是一个合法的A类地址,但他不是一个A类私有地址
第三条是一个C类地址,他的前24位掩码都是1,所以是一个合法的C类地址,而且他还是一个C类私有地址

第四条IP地址是错误的,所以计入错误IP地址或错误掩码

所以我们有1个A类地址,0个B类地址,1个C类地址,0个D类地址,0个E类地址,2个错误IP地址或错误掩码,1个私有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.*.*.*它不属于任何一类,也不属于不合法ip地址,所以清零

第二条符合127.*.*.*也不属于任何一类,所以清零

所以我们输出0 0 0 0 0 0 0

二、解题思路

1.首先我们需要定义一个s用来读取每一行的数据

每行的数据应该不超过

(3个数字*4组+4个点)*2 + 1个“~”符号 = 33个字符

2. 我们定义a,b,c,d,e用来存放这五类地址的个数,然后我们定义一个error来存放错误IP地址或错误掩码的个数,然后我们定义一个private存放私有IP的个数

3.我们逐行读取数据,并用strtok分割字符串,“~”左边的是IP,“~”右边的是子网掩码

4.我们将~左边的IP储存为char *ip,将~右边的子网掩码储存为char *subnetmask

5.首先我们对子网掩码进行判断

使用sscanf将子网掩码分成四个部分,sscan(subnetmask,“%d.%d.%d.%d", &s1, &s2, &s3, &s4)读取到四个整数变量中s1,s2,s3,s4

sscanf它的作用类似于scanf函数,但是sscanf是从给定的字符串str中读取数据,而scanf是从标准输入(通常是键盘)读取数据。

如果s1、s2、s3、s4全都是0或者全都是255那么证明这个子网掩码是错误的,我们不需要再检查ip地址了直接error++

如果s1、s2、s3、s4大于等于0小于等于255,那么我们开始检查他的前面是否全都是1,后面是否全都是0

(如果s1-4中任何一个部分小于0或者大于255那么也是错误掩码error++)

6.如果我们判断好子网掩码是正确的了,那么我们判断IP地址(否则直接error++不用判断IP)

同样用sscan,将ip地址分成四个部分,sscan(s,“%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)读取到四个整数变量中ip1,ip2,ip3,ip4

首先我们判断ip1是否是0或者127,如果ip1等于0或者127那么我们直接continue,进入下一次循环(读取下一行数据)

然后我们判断ip1、ip2、ip3、ip4是否全都是大于0小于256,如果是的话我们接着判断(如果不是的话我们error++)

先判断ip地址属于五类ip中的哪一类,判断ip1是属于1-126,128-191,192-223,224-239,240-255哪一个部分,然后分别对应部分的字母++

比如ip1>=1 && ip1<= 126的情况下我们a++

然后我们在a类的情况中还需要判断ip1是否等于10,如果是我们private++

在b类的情况中我们判断ip1是否等于172,如果是我们再判断ip2是否大于等于16小于等于31如果是,我们private++

在c类的情况中我们判断ip1是否是192,如果是我们再判断ip2是否是168,如果是我们private++

7.然后打印我们的a,b,c,d,e,error,private.(以空格隔开)

三、具体步骤

使用的语言是C

1.我们#include <stdio.h>引入输入输出库可以调用scanf、sscanf和printf函数

2.我们#include <string.h>库可以使用strtok函数,分割我们的字符串

3.我们进入主程序int main()

4.我们char s[33];

5.我们将计数器初始化

int a = 0;

int b = 0;

int c = 0;

int d = 0;

int e = 0;

int error = 0;

int private = 0;

6.逐行扫描进来输入直到没有数据

while(scanf("%32s", s) != EOF)

7.读入ip和subnetmask

char *ip = strtok(s, "~");

char *subnetmask = strtok(NULL, "~");

然后我们对子网掩码进行判断,先将其四个部分分别取出

unsigned int s1, s2, s3, s4;

sscan(subnetmask,“%d.%d.%d.%d", &s1, &s2, &s3, &s4);

我们定义一个notValid = 0;用来记录如果子网掩码不合法的话就跳过ip地址检查

如果是全0或者全1的情况我们记录非法

if((s1 == 0 && s2 == 0 && s3 == 0 && s4 == 0) || (s1 == 255 && s2 == 255 && s3 == 255 && s4 == 255))

error++;

notValid = 1;

检查合法性

else if(s1 >= 0 && s1 <= 255 && s2 >= 0 && s2 <= 255 && s3 >= 0 && s3 <= 255 && s4 >=0 && s4 <= 255) 

如果合法,从第一位二进制开始检查是否是1,直到检查到0,如果之后全是0那么证明合法,如果之后又碰到了1那么这个子网掩码错误

我们先将这四个部分都放到一个整数mask中

unsigned int mask = (s1 << 24) | (s2 << 16) | (s3 << 8) | s4;

然后对mask进行检查,如果

位了方便我们检查我们定义一个int find0 = 0;表示我们是否在子网掩码中从做往右检查的过程中,找到了0

for(int front1 = 31; front1 >= 0; front1--)

if(!(mask & (1 << front1)))

如果我们发现了0,那么我们find0 = 1;

if(find0 == 1 && (mask & (1 << front1)))

如果我们发现了0之后,又发现了1那么我们这个子网掩码不合法

我们error++,并且break;跳出for循环

我们用同样的方法将ip地址的四个部分取出来

并进行ip地址分类

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

int main() {
    char s[33];
    int a = 0;
    int b = 0;
    int c = 0;
    int d = 0;
    int e = 0;
    int error = 0;
    int private = 0;
    while (scanf("%s", s) != EOF) {
        //printf("our input is: %s\n", s);
        char* ip = strtok(s, "~");
        char* subnetmask = strtok(NULL, "~");
        //printf("ip : %s\nsubnetmask : %s\n", ip, subnetmask);
        int s1, s2, s3, s4;
        if ((sscanf(subnetmask, "%d.%d.%d.%d", &s1, &s2, &s3, &s4)) != 4) {
            error++;
            continue;
        }
        //printf("test s1: %d\n", s1);
        //现在我们开始对ip进行分类识别
        int ip1, ip2, ip3, ip4;
        if ((sscanf(ip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) != 4) {
            //读取有问题
            //printf("error reason4: reading problem, ip is not correct.\n");
            //printf("%s\n", ip);
            error++;
            continue;
        }
        //printf("after valid subnetmask the ip1 is%d\n", ip1);
        if (ip1 == 0 || ip1 == 127) continue;
        int notValid = 0;
        if ((s1 == 0 && s2 == 0 && s3 == 0 && s4 == 0) || (s1 == 255 && s2 == 255 &&
                s3 == 255 && s4 == 255)) {
            //printf("error reason1: subnetmask is all zero or one.\n");
            //printf("subnetmask is %d.%d.%d.%d\n", s1, s2, s3, s4);
            error++;
            notValid = 1;
        } else if (s1 >= 0 && s1 <= 255 && s2 >= 0 && s2 <= 255 && s3 >= 0 &&
                   s3 <= 255 && s4 >= 0 && s4 <= 255)  {
            unsigned int mask = (s1 << 24) | (s2 << 16) | (s3 << 8) | s4;
            //printf("mask : %u\n",mask);
            int find0 = 0;
            for (int front1 = 31; front1 >= 0; front1--) {
                if (!(mask & (1 << front1))) { //如果碰到了0,我们记录一下
                    find0 = 1;
                }
                if ((mask & (1 << front1)) &&
                        (find0 == 1)) { //如果已经碰到过0之后又碰到1那证明这个子网掩码错误
                    notValid = 1;
                    //printf("error reason2:subnet mask is not consecutive one and zero\n");
                    //printf("%u\n", mask);
                    error++;
                    //printf("the subnet mask in binary is:\n");
                    // for (int i = 31; i >= 0; i--) {
                    //     unsigned int bit = (mask >> i) & 1;
                    //     printf("%u", bit);
                    // }
                    //printf("\n");
                    //printf("this subnetmask is not valid!\n");
                    break;
                }
            }
        } else {
            //printf("error reason3: subnet mask not in ordinary range\n");
            //printf("%d.%d.%d.%d\n", s1, s2, s3, s4);
            error++;
        }
        //这个时候我们可以通过notValid来判断子网掩码是否是错误的,只有子网掩码正确的情况下我们才判断ip
        if (notValid) continue;

        if (ip1 > 0 && ip1 <= 255 && ip2 >= 0 && ip2 <= 255 && ip3 >= 0 && ip3 <= 255 &&
                ip4 >= 0 && ip4 <= 255) { // 如果我们的ip地址合法
            if (ip1 >= 1 && ip1 <= 126) {
                a++;
                //printf("a++ the ip1 is %d, ip2 is %d\n", ip1, ip2);
                if (ip1 == 10) {
                    private++;
                }
            } else if (ip1 >= 128 && ip1 <= 191) {
                b++;
                if (ip1 == 172) {
                    if (ip2 >= 16 && ip2 <= 31) {
                        private++;
                    }
                }
            } else if (ip1 >= 192 && ip1 <= 223) {
                c++;
                if ((ip1 == 192) && (ip2 == 168)) {
                    private++;
                }
            } else if (ip1 >= 224 && ip1 <= 239) {
                d++;
            } else if (ip1 >= 240 && ip1 <= 255) {
                e++;
            }
        } else {
            //printf("error reason5: ip is not in ordinary range.\n");
            //printf("%s\n", ip);
            error++;
        }
        //printf("\n");
    }
    printf("%d %d %d %d %d %d %d", a, b, c, d, e, error, private);
}

又写了一个放在function里的

#include <stdio.h>
#include <string.h>
#define VALIDIP(a, b, c, d) (a >= 0 && a <= 255 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0 && d <= 255 )


int isMaskValid(char* subnetmask) {
    int s1, s2, s3, s4;
    unsigned int mask;
    unsigned int max = -1;
    if ((sscanf(subnetmask, "%d.%d.%d.%d", &s1, &s2, &s3, &s4)) != 4) {
        return 0;
    } else if (VALIDIP(s1, s2, s3, s4)) {
        mask = (s1 << 24) | (s2 << 16) | (s3 << 8) | s4;
        if (mask == 0 || mask == max) return 0;
        else {
            while (!(mask & 1)) {
                mask >>= 1;
                max >>= 1;
            }
        }
    } else {
        return 0;
    }
    return mask == max;
}

void classifyIP(char* s, int* a, int* b, int* c, int* d, int* e, int* error,
                int* private) {
    char *ip = strtok(s, "~");
    char *subnetmask = strtok(NULL, "~");
    int i[4];
    if ((sscanf(ip, "%d.%d.%d.%d", &i[0], &i[1], &i[2], &i[3])) == 4) {
        if (VALIDIP(i[0], i[1], i[2], i[3])){
            if(i[0] == 0 || i[0] == 127) return;
            else if (isMaskValid(subnetmask)){
                if(i[0] < 127) {
                    (*a)++;
                    if(i[0] == 10) (*private)++;
                } else if(i[0] < 192){
                    (*b)++;
                    if(i[0] == 172 && i[1] == 31) (*private)++;
                } else if(i[0] < 224){
                    (*c)++;
                    if(i[0] == 192 && i[1] == 168) (*private)++;
                } else if(i[0] < 240) (*d)++;
                else (*e)++;
            } else {
                (*error)++;
            }
        } else {
            (*error)++;
        }
    } else {
        (*error)++;
    }
}

int main() {
    char s[33];
    int a = 0, b = 0, c = 0, d = 0, e = 0, error = 0, private = 0;
    while(scanf("%s", s) != EOF){
        classifyIP(s, &a, &b, &c, &d, &e, &error, &private);
    }
    printf("%d %d %d %d %d %d %d",a, b, c, d, e, error, private);
}

2024/10/29-21:34-2024/10/30-15:08

标签:int,HJ18,++,255.255,地址,&&,IP地址,掩码
From: https://blog.csdn.net/bingw0114/article/details/143350730

相关文章

  • 【shell脚本】利用Nmap扫描结果提取IP地址
    原创脚本家园在网络安全和运维管理中,我们常常需要扫描网络以获取设备信息,并对这些信息进行处理和分析。Nmap(NetworkMapper)是一款功能强大的网络扫描工具,它可以帮助我们获取网络中的设备信息,包括IP地址、MAC地址、开放的端口等。今天,我们将通过一篇实战文章,介绍如何利用Bash脚......
  • 验证IP地址
    验证IP地址题目链接:牛客描述编写一个函数来验证输入的字符串是否是有效的IPv4或IPv6地址IPv4地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为0-255,用(".")分割。比如,172.16.254.1;同时,IPv4地址内的数不会以0开头。比如,地址172.16.254.01是不合法的......
  • Python——查询IP地址地理位置与设备信息
    在这个数字化时代,IP地址不仅是设备与互联网通信的桥梁,它还蕴含着丰富的信息,比如地理位置、ISP(互联网服务提供商)和设备类型等。这些信息对于网络安全、用户行为分析以及个性化服务提供等方面都具有重要意义。本文将介绍一个Python脚本,它可以帮助用户查询指定IP地址的地理位置信......
  • NumPy掩码数组(Masked Arrays)教程
    简介在处理数据时,我们经常会遇到缺失或无效的数据条目。如果想在不删除这些数据的情况下跳过或标记它们,可能需要使用条件语句或过滤数据。NumPy的numpy.ma模块提供了掩码数组(maskedarrays)功能,可以更方便地处理这种情况。掩码数组是标准NumPyndarray和掩码(mask)的......
  • IP地址查询之数据清洗基本原理
    概:数据清洗的原理是在分析数据源特点的基础上,找出数据质量问题原因,确定清洗要求,然后建立起清洗模型,应用清洗算法、清洗策略和清洗方案对应到数据识别与处理中,最终清洗出满足质量要求的数据。对于数据源分析主要有两块,一个是了解数据源,数据清洗的第一步是深入了解数据源,包括数......
  • 初级python代码编程学习----简单的查看当前ip地址的图形化工具
    以下是一个使用Python的tkinter库创建图形化界面来查看当前IP地址的工具代码:代码importtkinterastkimportsocketdefget_ip_address():try:s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)s.connect(("8.8.8.8",80))ip......
  • Linux多ip地址如何删除多余ip
    问题场景:linux支持多个ip连接一个节点,但是ifconfig往往只列出其中一个ip,而ip命令能够显示所有ip,这可能会在某些场景造成一定问题,比如对本机有多ip不知情但又管理多客户机者,可能造成寻找困难的问题。比如:我一台俩ip机子执行ifconfig结果如下执行ipa可以看到如果只执行ifco......
  • Nginx配置基于IP地址的访问控制
    访问控制基于模块ngx_http_access_module实现,可以通过匹配客户端源IP地址进行限制在location中,通过allow、deny配置仅允许172.16.0.1的主机访问http://www.uhn.cn/admin其他地址均拒绝location=/admin{root/data/nginx/html/uhn;allow172.16.0.1/24;denyall;}locati......
  • 子网掩码划分的问题
    1ip地址分为网络位和主机位   总共32位     2   子网就是从主机地址借几位作为网络地址    假设子网为是x  则子网的个数是2的x次方,主机地址为y 则主机地址范围是2的y次方-2个2  题目  1.0.0.0/8的网络现在要求划分5个子网求......
  • 域名和IP地址收集
    实验介绍:被动信息收集是指通过搜索引擎数据库等,搜索目标的关键信息,较为隐蔽。主动信息收集则是需要主动向目标发送数据包一:域名信息收集域名用于数据传输时对计算机的定位dns使域名和IP相互映射whois是查询域名的ip和所有者的数据库1.Netcraft提供whois服务https://siter......