试解leetcode算法题--验证ip地址

<题目描述>
编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址。
IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 – 255, 用(“.”)分割。比如,172.16.254.1。
IPv6 地址由8组16进制的数字来表示,每组表示 16 比特。这些组数字通过 (“:”)分割。比如, 2001:0db8:85a3:0000:0000:8a2e:0370:7334。
<原题链接>
https://leetcode-cn.com/problems/validate-ip-address
<理明思路>
该题目给予的信息略少,有许多情况需要自己去考虑。
基本代码给了string型的函数,用来返回IPv4、IPv6和Neither三种字符串。
这里考虑到将字符串分为:1.普通字符串 2.类似IPv4格式的字符串 3.类似IPv6格式的字符串三种基本形式。因为感觉两种ip的各自分情况可能较多,因此另设了两个成员函数来分别对类似IPv4和IPv6的的字符串进行判断。

ps:
1. IPv4因为都是有数字组成,所以将字符串转换为数字在进行判断会易一些。
2. IPV6是十六进制难免会含有字母,因此将其当作字符串判断会易一些。
3. 不用考虑私有IP段不可联网的情况。

<样例代码>

#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std;
class Solution {
public:
    bool susIpv4(string str); //疑似Ipv4地址格式。
    bool susIpv6(string str); //疑似Ipv6地址格式。
    string validIPAddress(string IP) {
        int p=IP.find_first_of('.',0);
        int q=IP.find_first_of(':',0);
        if(IP.length()>50)
            return "Neither";
       /* cout<<"p="<<p<<" q="<<q<<endl; */
        if(p!=-1 && q==-1)          //如果只有'.'
        {
            if(susIpv4(IP))
                return "IPv4";
        }
        else if(p==-1 && q!=-1)    //如果只有':'
        {
            if(susIpv6(IP))
                return "IPv6";
        }
            return "Neither";
    }
};


bool Solution::susIpv4(string str){
    char *pstr = &str[str.length()-1];
    int i=3,j=1,xi;
    int ipfrg[4]={0,0,0,0};
    for(;pstr>&str[0];pstr--)
    {
        /* cout<<"i="<<i<<" *pstr="<<*pstr<<endl; */ 
        if(*pstr == '.' && *(pstr+1)== '0' && *(pstr+2)!= '.') 
        {
            if(*(pstr+2)!= '\0')
            {
                cout<<__LINE__<<" ";
                return false;
            }
        }
        if(*pstr == '.')  
        {
            i--;
            j=1;continue;
        }
        if(i<0  || (i==3&&(*pstr)=='.') ) 
        {
            cout<<__LINE__<<" ";
            return false;
        } 
        ipfrg[i]+=((*pstr)-48)*j;
        j*=10;
    } 
    xi=i;i=0;
    ipfrg[i]+=((*pstr)-48)*j; //将其换成整数。

    if(xi==0 && *(pstr)=='0' && *(pstr+1)!= '.') 
    {
        cout<<__LINE__<<" ";
        return false;  
    }
/* for(int x=0;x<4;x++) cout<<ipfrg[x]<<" "; cout<<"i= "<<i<<endl; //编码调试用、过后删掉。 */    
    if(ipfrg[0]>255||ipfrg[1]>255||ipfrg[2]>255||ipfrg[3]>255||xi!=0) 
    {
        cout<<__LINE__<<" ";
        return false;
    }

    pstr=&str[0];
    while(*pstr!='\0')
    {
        if(*pstr!='.')
        {
            if(!(*pstr>='0'&&*pstr<='9'))
            {
                cout<<__LINE__<<" ";
                return false;
            }
        }
       /* cout<<*pstr<<endl; */
        if((*pstr>='A'&&*pstr<='Z')|| 
        (*pstr>='a'&&*pstr<='z')||
        (*pstr=='.'&&*(pstr+1)=='.')||
        (*pstr=='.'&&*(pstr+1)=='\0')) 
        {
            cout<<__LINE__<<" ";
            return false;
        } 
        pstr++;
    }
    return true;
}

bool Solution::susIpv6(string str){
    transform(str.begin(),str.end(),str.begin(),::toupper); //全部变成大写字符便于判断。
    char *pstr = &str[0];
    int i = 0,count = 0;
    while(*pstr!='\0')      //不能用pstr!=NULL作为判断标准
    {
        if(*pstr!=':')
        {
            if(!((*pstr>='A'&&*pstr<='F')||(*pstr>='0'&&*pstr<='9')))
            {
                cout<<__LINE__<<endl;
                return false;
            }
        }
        if(*pstr == ':' && *(pstr+1) == ':')
        {
            cout<<__LINE__<<endl;
            return false;
        }//该判断必须再下一个if的前面。
        if(*pstr == ':')    //优先判断,该if语句位置不可任意调换。
        {
            count++;
            i=0;pstr++;
            continue;
        }
        if(i>3||*pstr>'F'||count>7) 
        {
                cout<<__LINE__<<endl;
                return false;
        } //长度过长.

        i++;
        pstr++;
    }if(count!=7) {cout<<__LINE__<<endl;return false;}
    return true; 
}
//日常省略main函数
  • IPv4可能出现的几种错误情况汇总:
    1.1.1.1.1
    1.1.1.1.
    0.0.0
    0.0.0.
    192.168.03.4
    255.255.-1.3
    .2.2.2
    11111111….(溢出)

  • IPv6错误情况较少,可以类比IPv4进行汇总。

点赞