首页 > 试题广场 >

判断两个IP是否属于同一子网

[编程题]判断两个IP是否属于同一子网
  • 热度指数:151590 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
IP地址是由4个0-255之间的整数构成的,用"."符号相连。
二进制的IP地址格式有32位,例如:10000011,01101011,00000011,00011000;每八位用十进制表示就是131.107.3.24
子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据。
子网掩码与IP地址结构相同,是32位二进制数,由1和0组成,且1和0分别连续,其中网络号部分全为“1”和主机号部分全为“0”。
你可以简单的认为子网掩码是一串连续的1和一串连续的0拼接而成的32位二进制数,左边部分都是1,右边部分都是0。
利用子网掩码可以判断两台主机是否在同一子网中。
若两台主机的IP地址分别与它们的子网掩码进行逻辑“与”运算(按位与/AND)后的结果相同,则说明这两台主机在同一子网中。


示例:
I P 地址  192.168.0.1
子网掩码  255.255.255.0

转化为二进制进行运算:

I P 地址   11000000.10101000.00000000.00000001
子网掩码 11111111.11111111.11111111.00000000

AND运算   11000000.10101000.00000000.00000000

转化为十进制后为:
192.168.0.0


I P 地址  192.168.0.254
子网掩码  255.255.255.0


转化为二进制进行运算:

I P 地址 11000000.10101000.00000000.11111110
子网掩码  11111111.11111111.11111111.00000000

AND运算  11000000.10101000.00000000.00000000

转化为十进制后为:
192.168.0.0

通过以上对两台计算机IP地址与子网掩码的AND运算后,我们可以看到它运算结果是一样的。均为192.168.0.0,所以这二台计算机可视为是同一子网络。

输入一个子网掩码以及两个ip地址,判断这两个ip地址是否是一个子网络。
若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2。

注:
有效掩码与IP的性质为:
1. 掩码与IP每一段在 0 - 255 之间
2. 掩码的二进制字符串前缀为网络号,都由‘1’组成;后缀为主机号,都由'0'组成



输入描述:

3行输入,第1行是输入子网掩码、第2,3行是输入两个ip地址
题目的示例中给出了三组数据,但是在实际提交时,你的程序可以只处理一组数据(3行)。



输出描述:

若IP地址或子网掩码格式非法则输出1,若IP1与IP2属于同一子网络输出0,若IP1与IP2不属于同一子网络输出2

示例1

输入

255.255.255.0
192.168.224.256
192.168.10.4
255.0.0.0
193.194.202.15
232.43.7.59
255.255.255.0
192.168.0.254
192.168.0.1

输出

1
2
0

说明

对于第一个例子:
255.255.255.0
192.168.224.256
192.168.10.4
其中IP:192.168.224.256不合法,输出1

对于第二个例子:
255.0.0.0
193.194.202.15
232.43.7.59
2个与运算之后,不在同一个子网,输出2

对于第三个例子,2个与运算之后,如题目描述所示,在同一个子网,输出0
          
#include <stdio.h>

int isValidMask(unsigned int* mask) {
    unsigned int temp = 0;
    
    for(int i=0;i<4;i++){
        if(mask[i] > 255){
            return -1;
        }
    }

    temp = ((mask[0] & 0xff) << 24) | ((mask[1] & 0xff) << 16) |
    ((mask[2] & 0xff) << 8) | (mask[3] & 0xff);
    //10000000 00000000 00000000 00000000 
    while(temp & (0x01 << 31)){
        temp <<= 1;
    }

    if(temp){
        return -1;
    }

    return 0;
}

int isValidIp(unsigned int* ip) {
    for(int i=0;i<4;i++){
        if(ip[i] > 255){
            return -1;
        }
    }
    return 0;
}

int isMatchSubNet(unsigned int *mask, unsigned int *ip1, unsigned int *ip2)
{
    for(int i=0; i < 4; i++){
        if((ip1[i] & mask[i]) != (ip2[i] & mask[i])){
            return -1;
        }
    }
    return 0;
}

int main() {
    unsigned int mask[4] = {0};
    unsigned int ip1[4] = {0};
    unsigned int ip2[4] = {0};

    int ret;
    ret = scanf("%u.%u.%u.%u", &mask[0], &mask[1], &mask[2], &mask[3]);
    if (4 != ret) {
        goto error;
    }

    if (0 != isValidMask(mask)) {
        goto error;
    }

    ret = scanf("%u.%u.%u.%u", &ip1[0], &ip1[1], &ip1[2], &ip1[3]);
    if (4 != ret) {
        goto error;
    }

    if (0 != isValidIp(ip1)) {
        goto error;
    }

    ret = scanf("%u.%u.%u.%u", &ip2[0], &ip2[1], &ip2[2], &ip2[3]);
    if (4 != ret) {
        goto error;
    }

    if (0 != isValidIp(ip2)) {
        goto error;
    }

    if(0 != isMatchSubNet(mask, ip1, ip2)){
        printf("2\n");
    }else {
        printf("0\n");
    }
    
    return 0;

error:
    printf("1\n");

    return 0;
}

发表于 2024-02-20 10:14:51 回复(0)
#include <stdio.h>

int main(void)
{
  int ip1[4], ip2[4], mask[4];
  unsigned int i, ret, mask_reserve, mask_flag, mask_value;
  
  while(scanf("%d.%d.%d.%d\r\n%d.%d.%d.%d\r\n%d.%d.%d.%d",
        &mask[0], &mask[1], &mask[2], &mask[3],
        &ip1[0], &ip1[1], &ip1[2], &ip1[3],
        &ip2[0], &ip2[1], &ip2[2], &ip2[3]) != EOF)
  {    
    ret = 0;
    mask_value = 0;
     
    for(i = 0; i < 4; i++)
    {
      if((ip1[i] < 0 || ip1[i] > 255)
        || (ip2[i] < 0 || ip2[i] > 255)
        || (mask[i] < 0 || mask[i] > 255))
      {
        ret = 1;
        break;
      }
      mask_value = (mask_value << 0x08) | mask[i];
    }
    
    mask_flag = 0;
    mask_reserve = 0;
    if(ret == 0)
    {
      for(i = 0; i < 32; i++)
      {
        if(((mask_value >> i) & 0x01) != mask_reserve)
        {
          if(mask_flag)
          {
            ret = 1;
            break;;
          }
          else
          {
            mask_flag = 1;
            mask_reserve = 1;
          }
        }
      }
    }
    
    if(ret == 0)
    {
      for(i = 0; i < 4; i++)
      {
        ip1[i] &= mask[i];
        ip2[i] &= mask[i];
        if(ip1[i] != ip2[i])
        {
          ret = 2;
          break;
        }
      }
    }
    
    printf("%d\r\n", ret);
  }
}

发表于 2022-08-16 17:09:09 回复(0)
255.255.252.0
173.225.245.45
69.138.93.228
这个网络掩码明明是错的,为什么还是2
发表于 2022-05-28 16:48:36 回复(0)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int iPtoInt(char *ptrIp, int iLen, unsigned int *ptr_ip_mac)
{
	if(strstr(ptrIp, (const char*)"..") != NULL )
	{
		return 0;
	}
	
	int k = 0, i = 0, j = 0;
	char arr[4][4] = {0};
	
	char *ptrtempIp = ptrIp;
	
	for(k = 0; k < iLen; k++)
	{
		if(i >= 4 || j >= 4)
		{
			return 0;
		}
		
		if(*ptrtempIp == '.')
		{
			ptrtempIp++;
			i++;
			j = 0;
			continue;
		}else{
			arr[i][j++] = *ptrtempIp;
			ptrtempIp++;
		}
	}
	
	if(i != 3)
	{
		return 0;
	}
	
	for(i = 0; i < 4; i++)
	{
		if(atoi(arr[i]) < 0 || atoi(arr[i]) > 255)
		{
			return 0;
		}
		
		unsigned int uiTemp = 0x000000FF;
		
		uiTemp &= atoi(arr[i]);
		
		*ptr_ip_mac |= (uiTemp << (24 - (8 * i)));
	}
	
	return 1;
}

int judugeIsMack(unsigned int uiMack)
{
	int i = 0, itage = 0;
	
	for(i = 0; i < 32; i++)
	{
		if((uiMack & 0x00000001) == 0x00000000)
		{
			if(itage == 1)
			{
				return 0;
			}
		}else{
			itage = 1;
		}
		
		uiMack = (uiMack >> 1);
	}
	
	return 1;
}

int main()
{
	char str[64] = {0};
	
	while(scanf("%s", str) != EOF)
	{
		unsigned int uiIp1 = 0x00000000, uiIp2 = 0x00000000, uiMask = 0x00000000;
		char str_ip1[32] = {0}, str_ip2[32] = {0};
		
		scanf("%s", str_ip1);
		scanf("%s", str_ip2);
		
		if(iPtoInt(str, strlen(str), &uiMask) == 0 || judugeIsMack(uiMask) == 0)
		{
			printf("1\n");
			continue;
		}
		
		if(iPtoInt(str_ip1, strlen(str_ip1), &uiIp1) != 1 || iPtoInt(str_ip2, strlen(str_ip2), &uiIp2) != 1)
		{
			printf("1\n");
			continue;
		}
		
		if((uiMask & uiIp1) == (uiMask & uiIp2))
		{
			printf("0\n");
		}else{
			printf("2\n");
		}
	}
	
	return 0;
}

发表于 2021-12-08 14:53:53 回复(0)
子网掩码的合法性使用 0x01进行按位异或
发表于 2021-11-27 22:05:16 回复(0)
#include <stdio.h>
#include <string.h>

#define MASK  1
#define IP    0

unsigned int arr2int (unsigned char *arr, int arrLen)
{
    unsigned long temp = 0 ;
    for(int i = 0; i < arrLen; i++)
    {
        temp <<=8;
        temp  |= arr[i];
    }
    return temp;
}


//合法性检查
int is_legal( char *ip, int is_mask)
{
    unsigned char buf[4] = {0};
    int j = 0;
    
    unsigned char arry_temp[32] = {0};
    strcpy(arry_temp, ip);
    char *temp = NULL;
    temp = strtok(arry_temp, ".");
    
    while(temp !=NULL)
    {
        if( atoi(temp) > 255 || atoi(temp) <0)
             return 1;
        buf[j] = atoi(temp); 
        j++;
       temp = strtok(NULL, ".");
    }
    
    if(is_mask == MASK)
    {
       unsigned int max_mask = 0xffffffff;
        while(( max_mask  <<= 1) > 0 )
        {
            if(arr2int (buf, 4)  ==  max_mask)
                return 0;
        } 
       return 1;
    }
     
    return 0;
}

//转为unsigned char
unsigned char * str2arr(char  *str, unsigned char * result)
{
    int j = 0;
    unsigned char arry_temp[32] = {0};
    
    strncpy(arry_temp, str, 32);
    char *temp = NULL;
    temp = strtok(arry_temp, ".");
    
    while(temp !=NULL)
    {
        result[j] = atoi(temp); 
        j++;
       temp = strtok(NULL, ".");
    }
    return  result;
}

//判断是否是统一网段
int is_samenet(char *mask, char *ip1, char *ip2)
{
    //合法性检查
   if( is_legal( mask, MASK) || is_legal( ip1, IP)|| is_legal( ip2, IP))
       return  1;
   
    //转为unsigned char
        
    unsigned char mask_int[4] = {0};
    unsigned char ip1_int[4] = {0};
    unsigned char ip2_int[4] = {0};
    str2arr(mask, mask_int);
    str2arr(ip1, ip1_int);    
    str2arr(ip2, ip2_int);
    
    //比较
    for(int i = 0; i < 4; i++)
    {
       if( (mask_int[i] & ip1_int[i]) != (mask_int[i] & ip2_int[i]))
         return 2;
    }
    return 0;
    
}


int main()
{
  unsigned char mask[32] = {0};
  unsigned char ip_1[32] = {0}; 
  unsigned  ip_2[32] = {0}; 

    
   //获取掩码
   while(scanf("%s", mask) != EOF)
   {
       scanf("%s", ip_1);
       scanf("%s", ip_2);
       printf("%d\n", is_samenet(mask, ip_1, ip_2));
   }
  return 0;
}

发表于 2021-09-01 13:22:04 回复(0)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int valid(char* ip, int ismask){
    char local_ip[16];
    strcpy(local_ip, ip);
    char* part;
    part = strtok(local_ip, ".");
    
    int last = 1;
    
    while (part){
        int p = atoi(part);
        if(p > 255 || p < 0) return 0;
        
        if (ismask){
            int p_list[10] = {0};
            p_list[0] = last;
            for (int i = 8; i >= 1; i--){
                p_list[i] = p % 2;
                p = p / 2;
            }
            for (int i = 0; i < 9; i++) if (p_list[i + 1] > p_list[i]) return 0; 
            last = p_list[8];
        }
        
        part = strtok(NULL, ".");
    }
    return 1;
}

int pow(int a, int b){
    int ret = 1;
    for (int i = 0; i < b; i++) ret*=a;
    return ret;
}

long subnet(char* mask, char*ip){
    char local_mask[16];
    char local_ip[16];
    strcpy(local_mask, mask);
    strcpy(local_ip, ip);
    
    char parts_mask[4][4] = {0};
    char parts_ip[4][4] = {0};
    
    char* p = strtok(local_mask, ".");
    for (int i = 0; i < 4; i++) {
        strcpy(parts_mask[i], p);
        p = strtok(NULL, ".");
    }
    
    p = strtok(local_ip, ".");
    for (int i = 0; i < 4; i++) {
        strcpy(parts_ip[i], p);
        p = strtok(NULL, ".");
    }
    
    long ret = 0;
    for (int i = 0; i < 4; i++){
        long a = atoi(parts_mask[i]);
        long b = atoi(parts_ip[i]);
        
        long c = pow(2, (3-i)*8);
        ret += (a & b) * c;
    }
    
    return ret;
}

int main(){
    char ip1[16];
    char ip2[16];
    char mask[16];
    
    while (scanf("%s %s %s", mask, ip1, ip2) == 3){
        
        if ((valid(mask, 1) && valid(ip1, 0) && valid(ip2, 0)) == 0) printf("1\n");
        else if (subnet(mask, ip1) - subnet(mask, ip2) == 0) printf("0\n");
        else printf("2\n");
    }
}


发表于 2021-08-27 15:47:48 回复(0)

问题信息

难度:
8条回答 54045浏览

热门推荐

通过挑战的用户

查看代码