题目描述
输入一个字符串, 表示需要检查的字符串。
输出描述
输出为一行。
如果是合法的IPV4地址,则输出"IPv4"; 如果是合法的IPV6地址,则输出"IPV6"; 否则输出"Neither".
样例输入
172.16.254.1
2001:0db8:85a3:0:0:8A2E:0370:7334
256.256.256.25
样例输出
IPv4
IPv6
输入一个字符串,检查输入是否为合法的IPV4或者IPV6地址。
IPV4地址: 由4组数字组成,每组数字由"."分隔,第1组每个数字在1到255之间,其余组每个数字在0到255之间。如"172.16.254.1"是一个合法的地址,但是每组数字是不能包含前导0的,如"172.16.254.01"不是一个合法的IPV4地址。
IPV6地址: IPV6地址是有8组16进制数字组成的,每组有4个16进制数字,每组数字之间用":"分隔开。例如"2001:0db8:85a3:0000:0000:8a2e:0370:7334"是一个合法的IPV6地址。在IPV6地址中,可以忽略数字之间的前导0,同时里面的字符不区分大小写,例如"2001:db8:85a3:0:0:8A2E:0370:7334"也是合法的IPV6地址。需要注意的是,每组数字不能为空,例如"2001:0db8:85a3::8A2E:0370:7334"不是合法的IPV6地址。
输入描述输入一个字符串, 表示需要检查的字符串。
输出描述
输出为一行。
如果是合法的IPV4地址,则输出"IPv4"; 如果是合法的IPV6地址,则输出"IPV6"; 否则输出"Neither".
样例输入
172.16.254.1
2001:0db8:85a3:0:0:8A2E:0370:7334
256.256.256.25
样例输出
IPv4
IPv6
Neither
Talk is cheap,show me the code!
#include<iostream> #include<cstdlib> #include<string> using namespace std; int Char_to_Int(string, int, int); bool Judge_IPv4(string); bool Judge_IPv6(string); int main() { string s; getline(cin, s);//注意!使用cin会忽略空格,所以用getline来接收空格! if (Judge_IPv4(s)) cout << "IPv4";//如果是IPv4地址,输出IPv4 else if (Judge_IPv6(s)) cout << "IPv6";//如果是IPv6地址,输出IPv6 else cout << "Neither";//都不是,输出Neither return 0; } bool Judge_IPv4(string s) { int len = s.length(); if (s[0] == '.' || s[len - 1] == '.') return false;//如果第一个或最后一个字符是点,则不合法 int count_dot = 0;//计数点个数,初始化为0 for (int i = 0; i < len; i++) { if ((s[i]<'0' || s[i]>'9') && s[i] != '.') return false;//如果字符不是数字,也不是点,则不合法 if (s[i] == '.')//如果碰到点 { count_dot++;//点数+1 if (s[i + 1] == '.') return false;//如果有连续两个点,说明是空组,不合法 int end = i - 1;//记录点之前的组的末位置 int j = end; for (; j >= 0; j--)//从点之前的组的末位置往前扫描 if (s[j] == '.')//如果碰到第二个点,跳出循环 break; //如果没碰到点,说明点之前的组为起始组,j循环结束后为-1 int start = j + 1;//记录点之后的组或起始组的起始位置 if ((end-start+1)>=2&&s[start] == '0') return false;//重点!如果当前组位数大于等于2且起始位置上的字符为0,说明是前导0,不合法 int n = Char_to_Int(s, start, end);//将从起始位置开始到末位置之间的字符转换成数字 if (start == 0)//因为起始组数的范围是1到255,故需要单独处理 { if (n < 1 || n>255) return false;//如果数值在1到255之外,则不合法 } else if (n < 0 || n>255) return false;//如果数值在0到255之外,则不合法 } } if (count_dot != 3) return false;//如果点数不为3,则不合法 for(int i=len-1;i>=0;i--)//处理最后一组字符的情况,从末尾开始倒上来扫描 if (s[i] == '.')//如果碰到点 { int start = i + 1;//记录点之后的组的起始位置 int end = len - 1;//记录点之后的组的末位置即字符串的末位置 if ((end - start + 1) >= 2 && s[start] == '0') return false;//重点!如果当前组位数大于等于2且起始位置上的字符为0,说明是前导0,不合法 int n = Char_to_Int(s, start, end);//将从起始位置开始到末位置之间的字符转换成数字 if (n < 0 || n>255) return false;//如果数值在0到255之外,则不合法 break;//注意!处理完后要及时跳出循环! } return true; } int Char_to_Int(string s, int start, int end) {//将字符转换为数字 int len = s.length(); //如果单独看此函数,则需要判定形参start和end是否合法 if (start < 0 || end == len||start>end) { cout << "Illegal Subscript!"; exit(0); } int num = 0; for (int i = start; i <= end; i++) num = num * 10 + (s[i] - '0');//将当前字符的ASCII码减去0的ASCII码即当前字符对应的数字 //然后按照10进制从高位到低位累加和 return num; } bool Judge_IPv6(string s) { int len = s.length(); if (s[0] == ':' || s[len - 1] == ':') return false;//如果第一个或最后一个字符是冒号,则不合法 int count_colon = 0;//计数冒号数,初始化为0 int count_bit=0;//计数每组位数,初始化为0 for (int i = 0; i < len; i++) { if ((s[i]<'a' || s[i] > 'f') && (s[i] < 'A' || s[i] > 'F') && (s[i] < '0' || s[i] > '9')&&s[i]!=':') return false;//如果字符不是16进制中的字母,不是数字,也不是冒号,则不合法 count_bit++;//如果字符合法,则位数+1 if (s[i] == ':')//如果碰到冒号 { count_bit = 0;//位数清0,重新计数 count_colon++;//冒号数+1 if (s[i + 1] == ':') return false;//如果有连续两个冒号,说明是空组,不合法 } if (count_bit > 4)//如果每组位数超过4,则不合法 return false; } if (count_colon != 7)//如果冒号数不为7,则不合法 return false; return true; }