0
点赞
收藏
分享

微信扫一扫

[字符串]BM85 验证IP地址-中等

​​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 是无效的。


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

数据范围:字符串长度满足 [字符串]BM85 验证IP地址-中等_字符串进阶:空间复杂度 [字符串]BM85 验证IP地址-中等_字符串_02,时间复杂度 [字符串]BM85 验证IP地址-中等_字符串_02

示例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

题解

思路:

  1. 先计算ipv4和ipv6的最大、最小长度,根据长度去除掉那些长度非法的字符串
  2. 查找字符串的前5个字符,如果'.'和':'都不存在,则是非法ip
  3. 如果是找到'.',则按ipv4进行验证,否则ipv6
  4. ipv4:必须有3个'.',且以其为分割符分割的字符中只能有0~9,最长3个字节,二进制值0~255,且第一个分段不能以0开头
  5. 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
#include <bits/stdc++.h>

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";
}
举报

相关推荐

0 条评论