首页 > 试题广场 >

验证IP地址

[编程题]验证IP地址
  • 热度指数:96085 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址

IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 - 255, 用(".")分割。比如,172.16.254.1;
同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。

IPv6 地址由8组16进制的数字来表示,每组表示 16 比特。这些组数字通过 (":")分割。比如,  2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以是小写。所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 address地址 (即,忽略 0 开头,忽略大小写)。

然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现 (::) 的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。
同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。

说明: 你可以认为给定的字符串里没有空格或者其他特殊字符。

数据范围:字符串长度满足 5 \leq n \leq 50
进阶:空间复杂度 ,时间复杂度
示例1

输入

"172.16.254.1"

输出

"IPv4"

说明

这是一个有效的 IPv4 地址, 所以返回 "IPv4" 
示例2

输入

"2001:0db8:85a3:0:0:8A2E:0370:7334"

输出

"IPv6"

说明

这是一个有效的 IPv6 地址, 所以返回 "IPv6" 
示例3

输入

"256.256.256.256"

输出

"Neither"

说明

这个地址既不是 IPv4 也不是 IPv6 地址 

备注:
ip地址的类型,可能为
IPv4,   IPv6,   Neither
int strsearch(char* s, char c) {
    int i;
    for(i=0;i<strlen(s);i++) {
        if(s[i]==c)
            return i;
    }
    return -1;
}
bool judgenum(char* s, int n) {
    int i,num=0;
    if(!n)
        return false;
    for(i=0;i<n;i++) {
        if((s[i]<'0')||(s[i]>'9'))
            return false;
        if((i==0)&&(s[i]=='0')&&(n!=1))
            return false;
        num *= 10;    
        num += s[i]-'0';
    }
    printf("num:%d\n", num);
    if(num>255)
        return false;
    return true;
}

bool judge4hex(char* s, int n) {
    int i;
       
    if((n>4)||(n==0))
        return false;
   
    for(i=0;i<n;i++) {
        if(!(((s[i]>='0')&&(s[i]<='9'))||((s[i]>='a')&&(s[i]<='f'))||((s[i]>='A')&&(s[i]<='F'))))
            return false;
    }
    return true;
}
char* solve(char* IP ) {
    // write code here
    static char res[] = "Neither";
   
    {
        int i;
        for(i=1;i<5;i++) {
            if(IP[i]=='.'){
                strcpy(res, "IPv4");
                break;
            }
            else if(IP[i]==':'){
                strcpy(res, "IPv6");
                break;
            }
        }
    }

    if(!strcmp(res, "IPv4")) {
        int i;
        int Point_LOC=0;
        for(i=0;i<4;i++) {
            int NumLength = strsearch(IP+Point_LOC,'.');
            if(NumLength>0) {
                if(!judgenum(IP+Point_LOC,NumLength))
                    return "Neither";
                Point_LOC += NumLength+1;
            }
            else {
                if(!judgenum(IP+Point_LOC,strlen(IP)-Point_LOC))
                    return "Neither";
                Point_LOC += NumLength+1;
                break;
            }
        }
    }
    else if(!strcmp(res, "IPv6")) {
        int i;
        int Point_LOC=0;
        for(i=0;i<9;i++) {
            int NumLength = strsearch(IP+Point_LOC,':');
            if((i==8)&&(NumLength!=-1))
                return "Neither";
            if(NumLength>0) {
                if(!judge4hex(IP+Point_LOC,NumLength))
                    return "Neither";
                Point_LOC += NumLength+1;
            }
            else {  
                if(!judge4hex(IP+Point_LOC,strlen(IP)-Point_LOC))
                    return "Neither";

                Point_LOC += NumLength+1;
                break;
            }
        }
    }

    return res;
}

发表于 2024-03-13 15:28:52 回复(0)
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 验证IP地址
 * @param IP string字符串 一个IP地址字符串
 * @return string字符串
 */
#include <string.h>
char* solve(char* IP ) {
    // write code here

    //这里先验证几个字符串转数数字函数
    //十六进制字符串转数字

    // char str[] = "0db8";
    // int num;
    // sscanf(str, "%x", &num);
    // printf("%d", num);

    //十进制字符串转数字
    // char str[] = "053";
    // int num;
    // num = atoi(str);
    // printf("%d", num);

    char inspec_ipv4[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";  //检查数组 IP中不能有检查数组中的内容
    char inspec_ipv6[] = "ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ";  //对于16进制检查数组来说。不能有超过f的内容
    // printf("%ld",strspn(str1, IP));  //通过strspn函数可以直接检查前一个字符串中有多少字符是后一个字符串中有的。返回数量。对前一个字符串挨个检查  所以前一个字符串可以搞一个字符集挨个检查


    //此处开始题目要求的逻辑代码
    char ipv4_split[] = ".";
    char ipv6_split[] = ":";
    char *estr;

    //首先是区分IP是IPV4还是IPV6。通过字符串长度来区分
    if(strlen(IP) >= 7 && strlen(IP) <= 15)  //字符串长度在7到15之间是IPV4地址  这个判断条件进入就表示肯定不是IPv6地址
    {   
        //还要排除IPv4中混有字母的情况
        if(strcspn(inspec_ipv4, IP) != 52)  //inspec_ipv4中连续52个都不在IP中才可以
        {
            return "Neither";
        }

        //strtok实际作用分割出来多个字符串,每调用一次时就会返回将指针指向的字符串,并将指针指向下一个字符串
        estr = strtok(IP, ipv4_split);  //这个strtok使用时必须先完整字符串作为输入参数一遍之后都要调NULL
        // printf("%s",estr);
        

        // printf("%s ",estr);
        if(estr[0] == '0' && strlen(estr) > 1)
        { //这里if的判断条件也是排除只有一个0的正确情况
            return "Neither";
        }
        //还要判断范围
        int num;
        num = atoi(estr);
        if(num > 255)
            return "Neither";

        while((estr = strtok(NULL, ipv4_split)))
        {
            // printf("%s ",estr);
            
            //对分割结果的每个字符串进行首位判断检索  
            if(estr[0] == '0' && strlen(estr) > 1)  //如果某一位置的IP地址首位就是0(192.168.01.12)。则不符合IPV4的规则。直接返回错误
            { //这里if的判断条件也是排除只有一个0的正确情况
                return "Neither";
            }

            //还要判断范围
            num = atoi(estr);
            if(num > 255)
                return "Neither";
        }

        //上面的错误校验都通过了
        return "IPv4";
    }
    else//下面是判断IPv6地址是否正确
    {
        if(IP[strlen(IP) - 1] == ':')
            return "Neither";

        //还要排除IPv6中混有非16进制字母的情况
        if(strcspn(inspec_ipv6, IP) != (52-12))
        {
            return "Neither";
        }

        //根据题目要求。有一种存在连续冒号的情况为错误情况也要排除
        if(NULL != strstr(IP, "::"))  //检查IP字符串中是否有连续冒号。有的话直接返回错误
        {
            return "Neither";
        }

        estr = strtok(IP, ipv6_split);
        if(strlen(estr) > 4)
        { //这里if的判断条件也是排除只有一个0的正确情况
            return "Neither";
        }
        while((estr = strtok(NULL, ipv6_split)))
        {
            // printf("%s ",estr);
            //对分割结果的每个字符串进行首位判断检索  
            if(strlen(estr) > 4)  //如果某一位置的IP地址首位就是0(192.168.01.12)。则不符合IPV4的规则。直接返回错误
            { //这里if的判断条件也是排除只有一个0的正确情况
                return "Neither";
            }
        }

        //上面的错误校验都通过了
        return "IPv6";
    }

    return IP;
}

发表于 2023-10-03 18:47:15 回复(0)
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define IPV4 "IPv4"
#define IPV6 "IPv6"
#define NO    "Neither"
#define ERRORV4 "1234567"

char* solve(char* IP ) {
    int countV6 = 0;
    int countV4 = 0;
    char* temp;

    for (int i = 0; i < strlen(IP); i++) {
        if (IP[i] == ':')
            countV6++;
        if (IP[i] == '.')
            countV4++;
    }
    if (countV4 == 3) {
        temp = strtok(IP, ".");
        countV4--;
        if (atoi(temp) < 0 || atoi(temp) > 255 || temp[0] == '0' ||
                (atoi(temp) < (int)pow(10, strlen(temp) - 1)))
            return NO;
        while (temp != NULL) {
            temp = strtok(NULL, ".");
            if (!temp)
                break;
            countV4--;
            if (atoi(temp) < 0 || atoi(temp) > 255 || temp[0] == '0' ||
                    (atoi(temp) < (int)pow(10, strlen(temp) - 1)))
                return NO;
        }
        if (countV4 == -1) //避免"..165.1"
            return IPV4;
        else
            return NO;
    } else if (countV6 == 7) {
        temp = strtok(IP, ":");
        countV6--;
        if (strlen(temp) > 4  || (temp[0] == '0' && temp[1] == '0')){
            return NO;
        }else{
            for (int j = 0; j < strlen(temp); j++) {
                int data = (int)temp[j];
                if ((data > 0x46 && data < 0x61) || (data > 0x72))
                    return NO;
            }
        }
        while (temp != NULL) {
            temp = strtok(NULL, ":");
            if (!temp)
                break;
            countV6--;
            if (strlen(temp) > 4  || (temp[0] == '0' && temp[1] == '0')){
                return NO;
            }else{
                for (int j = 0; j < strlen(temp); j++) {
                    int data = (int)temp[j];
                    printf("%d\n", data);
                    if ((data > 0x46 && data < 0x61) || (data > 0x72))
                        return NO;
            }
        }

        }
        if (countV6 == -1)
            return IPV6;
        else
            return NO;
    } else {
        return NO;
    }
}


编辑于 2023-08-22 12:01:39 回复(0)
/**
 * 验证IP地址
 * @param IP string字符串 一个IP地址字符串
 * @return string字符串
 *
 * C语言声明定义全局变量请加上static,防止重复定义
 */
int isipv4(char *IP)
{
    int i = 0, j = 0, flag = 0, num_0 = 0, count = 0;
    int len = strlen(IP);
    while(i < len )
    {
        j = i;
        num_0 = 0;
        while(*(IP + j) == '0')
        {
            num_0 ++;
            j ++;
        }
        if(num_0) 
        {
            if(num_0 == 1 &&  (*(IP + j) == '.' || *(IP + j) == '\0' ))
            {
                count ++;
            }
            else
            {
                return 0;
            }
        }
        else
        {
            flag = 0;
            while(*(IP + j) != '.' && *(IP + j) != '\0')
            {
                if(*(IP + j) < '0' || *(IP + j) > '9') return 0;
                flag = 10 * flag + *(IP + j) - '0';
                j ++;
            }
            if(flag < 0 || flag > 255) return 0;
            else count ++;
        }
        i = j + 1;
    }
    if(count == 4) return 1;
    else return 0;
}
int isipv6(char *IP)
{
    int i = 0, j = 0, flag = 0, num_0 = 0, count = 0;
    int len = strlen(IP);  
    while(i < len)
    {
        j = i;
        flag = 4;
        num_0 = 0;
        while(*(IP + j) == '0')
        {
            num_0 ++;
            j ++;
            flag --;
        }
        if(num_0 >= 4) 
        {
            return 0;
        }
        else
        {
            
            if(num_0 == 1 &&  (*(IP + j) == ':' || *(IP + j) == '\0' ))
            {
                count ++;
            }
            else
            {
                while(*(IP + j) != ':' && *(IP + j) != '\0')
                {
                    if(((*(IP + j) >= '0' && *(IP + j) <= '9') || (*(IP + j) >= 'a' && *(IP + j) <= 'f') || (*(IP + j) >= 'A' && *(IP + j) <= 'F')  ))
                    {
                        flag --;
                    }
                    else
                    {
                        return 0;
                    }
                    j ++;
                }
                if(flag == 0) count ++;
                else return 0;
            }
        }
        i = j + 1;
    }
    if(count == 8) return 1;
    else return 0;
}
char* solve(char* IP ) {
    // write code here
    int i  = 0, j = 0 ;
    int num_4 = 0, num_6 = 0;
    while( *(IP + i) != '\0' )
    {
        if(*(IP + i) == '.')
        {
            num_4 ++;
        }
        else if(*(IP + i) == ':')
        {
            num_6 ++;
        }
        i ++;
    }
    if(num_4 == 3)
    {
       if(isipv4(IP)) return "IPv4";
        else return "Neither" ;
    }
    else if(num_6 == 7)
    {
       if(isipv6(IP)) return "IPv6";
        else return "Neither" ;        
    }
    return "Neither";
}

发表于 2022-03-09 22:46:12 回复(0)