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 是无效的。
说明: 你可以认为给定的字符串里没有空格或者其他特殊字符。
数据范围:字符串长度满足 进阶:空间复杂度
,时间复杂度
示例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
题解
思路:
- 先计算ipv4和ipv6的最大、最小长度,根据长度去除掉那些长度非法的字符串
- 查找字符串的前5个字符,如果'.'和':'都不存在,则是非法ip
- 如果是找到'.',则按ipv4进行验证,否则ipv6
- ipv4:必须有3个'.',且以其为分割符分割的字符中只能有0~9,最长3个字节,二进制值0~255,且第一个分段不能以0开头
- ipv6:必须有7个':',且以':'分割的字符串不能为空,只能取数字、a~f的大小写,且第一个的二进制值不能为0
下面的代码没有判断分割符号的个数,也能100%过测试用例,应该是测试用例不够充足,也可以把这块逻辑加上~~
// https://www.nowcoder.com/practice/55fb3c68d08d46119f76ae2df7566880?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
using namespace std;
// ipv6最短1:0:0:0:0:0:0:0,最短十五个字节
// 最长 8*4+7 = 39
bool is_ipv6(const std::string &ip)
{
int last_end = -1;
int value = 0;
for (int i = 0; i < ip.size(); ++i)
{
if (ip[i] != ':' && !(ip[i] >= '0' && ip[i] <= '9') && !(ip[i] >= 'a' && ip[i] <= 'f') && !(ip[i] >= 'A' && ip[i] <= 'F'))
{
return false;
}
if (i == ip.size() - 1 && ip[i] == ':')
{
return false;
}
if (ip[i] == ':')
{
int len = i - last_end - 1;
if (len <= 0 || len > 4 || (last_end == -1 && (value == 0)))
{
return false;
}
value = 0;
last_end = i;
}
else
{
value = value * 10 + (ip[i] - '0'); // 这里的value仅仅用于判断开头的是否为0,因此只需要和字符0比较即可,并不是为了计算真实的值
}
}
return true;
}
// ipv4最长:255.255.255.255,最长15字节
// 最短 1.0.0.0 最短7个字节
bool is_ipv4(const std::string &ip)
{
int last_end = -1;
int value = 0;
for (int i = 0; i < ip.size(); ++i)
{
if (ip[i] != '.' && !(ip[i] >= '0' && ip[i] <= '9'))
{
return false;
}
if (ip[i] == '.')
{
int len = i - last_end - 1;
if (len <= 0 || (len >= 2 && ip[last_end + 1] == '0') || value > 255 || (last_end == -1 && value == 0))
{
return false;
}
value = 0;
last_end = i;
}
else
{
value = value * 10 + (ip[i] - '0');
}
}
return true;
}
string solve(string ip)
{
int len = ip.size();
if (len < 7 || len > 39)
{
return "Neither";
}
size_t pos = ip.find_first_of('.');
if (pos != ip.npos)
{
return is_ipv4(ip) ? "IPv4" : "Neither";
}
pos = ip.find_first_of(':');
if (pos != ip.npos)
{
return is_ipv6(ip) ? "IPv6" : "Neither";
}
return "Neither";
}