<题目描述>
编写一个函数来验证输入的字符串是否是有效的 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进行汇总。