牛客-C语言解法-验证IP地址

题目链接:

验证IP地址_牛客题霸_牛客网 (nowcoder.com)

题目简介:

描述

编写一个函数来验证输入的字符串是否是有效的 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≤n≤50

进阶:空间复杂度 O(n),时间复杂度O(n)

题目解法:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/*
 *BM85 验证IP地址
描述
    编写一个函数来验证输入的字符串是否是有效的 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 5≤n≤50
进阶:空间复杂度 O(n) ,时间复杂度 O(n) 
*/

/**
 * 验证IP地址
 * @param IP string字符串 一个IP地址字符串
 * @return string字符串
 */
#define PROTOCOL_NEITHER 0      //协议类型
#define PROTOCOL_IPV4 1
#define PROTOCOL_IPV6 2

/// @brief 判断是否有效字符
/// @param c  输入字符
/// @return     0:有效;  -1,无效字符
int isVaildChar(char c){         
    if(c >= 'A' && c <='F')      
        return 0;
    if(c >= 'a' && c <='f')
        return 0;
    if(c >= '0' && c <='9')
        return 0;
    return -1;           
}

int IsProtocalIPV4(char *IP){
    char *tmpIp = IP;
    int sectorNum = 0;  //用于存储每一段字符的十进制值
    int sector = 0;     //用于存储输入的IP有多少段
    do{     //do while才能判断到结束符
        if(*tmpIp == '.' || *tmpIp == '\0'){        //完成一小段的字符获取后,进入判断,是否到末尾以及该段字符是否合法。
            if(sectorNum > 255) return -1;          //如果该段字符十进制大于255,非法
            sectorNum = 0;          //该段字符合法         ,  清空sectorNum,为下段字符做准备
            sector++;                                        //IP段+1
            if(*tmpIp == '\0') break;               //如果已经到达末尾,则跳出循环。
            tmpIp++;                                         //跳过.
        }
        if(*tmpIp >= '0' && *tmpIp <= '9'){                 //判断字符是否为数字
            if(sectorNum == 0 && *tmpIp == '0' && *(tmpIp+1) != '.')return -1;   //ipv4中每一段开头不能为0,否则非法
            sectorNum *= 10;                                //正常字符以十进制存放在sectorNum
            sectorNum += (*tmpIp - '0');
        }else{                                              //异常字符则退出函数
            return -1;
        }
    }while(*tmpIp++ != '\0');

    if(sector != 4)             //判断是否有4段,多或少都为非法
        return -1;
    return 0;
}

int IsProtocalIPV6(char *IP){
    char *tmpIp = IP;           
    int sectorCount = 0;    //小段的字符数量,注意这里和v4不一样
    int sector = 0;         //用于存储输入的IP有多少段

    do{
        if(*tmpIp == ':' || *tmpIp == '\0'){
            if(sectorCount == 0 || sectorCount > 4) return -1;  //小段的字符数量为0或者大于4都是非法
            sectorCount = 0;                //清空小段字符数量,为下一次做准备
            sector++;                       //段+1
            if(*tmpIp == '\0') break;       //如果已经到达末尾,则跳出循环
            tmpIp++;                        //跳过:
        }
        if(isVaildChar(*tmpIp) == 0){       //判断字符是否为合法:0-9 a-f A-F
            sectorCount++;
        }else{                              //异常字符则退出函数
            return -1;
        }
    }while(*tmpIp++ != '\0');

    if(sector != 8)     //判断是否有8段,多或少都为非法
        return -1;
    return 0;
}

char* solve(char* IP ) {
    // write code here
    char *tmpIp = IP;
    char *ret = (char*)malloc(sizeof(char)*10);     //给返回值申请空间
    ret = "Neither";                                
    int flag_process = PROTOCOL_NEITHER;            //设置协议的默认值
    while(*tmpIp != '\0'){                          //根据. :来区分是使用v4 v6的协议
        if(*tmpIp == '.'){
            flag_process = PROTOCOL_IPV4;
            break;
        }
        if(*tmpIp == ':'){
            flag_process = PROTOCOL_IPV6;
            break;
        }
        tmpIp++;
    }

    if(flag_process == PROTOCOL_IPV4){              //Ipv4解析
        if(IsProtocalIPV4(IP) == 0){                //如果校验完成则设置返回值ret为IPv4
            ret = "IPv4";
        }
    }else if(flag_process == PROTOCOL_IPV6){        //Ipv6解析
        if(IsProtocalIPV6(IP) == 0){
            ret = "IPv6";
        }
    }
    return ret;
}

/**************************end******************************************/

int main ()
{
    char *ip1 = "172.16.254.1";
    char *ip2 = "2001:0db8:85a3:0:0:8A2E:0370:7334";
    char* ret = solve(ip2);
    printf("\r\nret:  %s", ret);
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值