一、题目
编写一个函数来验证输入的字符串是否是有效的 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)方法一:使用正则判断
史上最全正则表达式语法,文末附常用表达式!_藏经阁-CSDN博客_正则表达式语法
/**
* 验证IP地址
* @param IP string字符串 一个IP地址字符串
* @return string字符串
*/
function solve( IP ) {
//1. IPv4:
//一位时:为0 或 非零数字;多位时,为[1-9]范围内的数字; 并且数字<256
let ipv4 = IP.split(".");
if(ipv4.length===4 && ipv4.every(item => /^0$|^[1-9]\d{0,2}$/.test(item) && item<256)){
return 'IPv4';
}
//2. IPv6
//四位,取值范围为[0-9]、[A-F]、[a-f]
let ipv6 = IP.split(":");
if(ipv6.length===8 && ipv6.every(item => /^[0-9A-Fa-f]{1,4}$/.test(item))){
return 'IPv6';
}
//3. 其它
return "Neither"
}
module.exports = {
solve : solve
};
d:匹配数字
^:匹配字符串的开始
$:匹配字符串的结束
{n,m}:重复n到m次
\d{3,6}:匹配3到6位数字
+:重复一次或更多次
[1-9]:限定1到9
[a-f]:限定a到f
^[A-Za-z0-9]+$ :由数字和26个英文字母组成的字符串
(2)方法二:分治法
IPv4 和 IPv6 地址均是由特定的分界符隔开的字符串组成,并且每个子字符串具有相同格式。
因此,可以将地址分为多个块,然后逐块进行验证。
算法
- 对于 IPv4 地址,通过界定符 . 将地址分为四块;对于 IPv6 地址,通过界定符 : 将地址分为八块。
- 对于 IPv4 地址的每一块,检查它们是否在 0 - 255 内,且没有前置零。
- 对于 IPv6 地址的每一块,检查其长度是否为 1 - 4 位的十六进制数。
/**
* 验证IP地址
* @param IP string字符串 一个IP地址字符串
* @return string字符串
*/
function solve( IP ) {
//1. IP中有三个 点 IPv4
if(IP.split("").filter(ch => ch==".").length ===3){
return validateIPv4(IP);
}else if(IP.split("").filter(ch => ch==":").length === 7){
//2. IP中有7个冒号 IPv6
return validateIPv6(IP);
}else{
return "Neither"
}
}
function validateIPv4(ip){
//判断是否在 0 - 255 内,且没有前置零
let arr = ip.split(".");
for(let i=0;i<arr.length;i++){
if(arr[i].length<=0 || arr[i].length>3){//1. 长度不在1-3范围内
return "Neither"
}
if(arr[i][0]=='0' && arr[i].length>1){//2. 存在前置0
return "Neither"
}
if(isNaN(arr[i]) || arr[i]-'0'<0 || arr[i]-'0'>255){ //3.非数字 或 数字范围不合法
return "Neither"
}
}
return "IPv4"
}
function validateIPv6(ip){
let arr = ip.split(":");
let str = "0123456789abcdefABCDEF";
for(let i=0;i<arr.length;i++){
if(arr[i].length<=0 || arr[i].length>4){ //1. 每组数字位数为1~4位
return "Neither"
}
// if(arr[i]=="00" || arr[i]=="000" || arr[i]=="0000"){ //2. 存在多余的0(允许存在多余零)
// return "Neither"
// }
//3. 存在不合法字符
// arr[i] = parseInt("0x"+arr[i]);
// if(arr[i]>65535 || arr[i]<0) return "Neither"
if(arr[i].split("").some(value => {return str.indexOf(value)==-1})){
return "Neither"
}
}
return "IPv6"
}
module.exports = {
solve : solve
};