|
| 1 | +# 13.如何验证一个 IP 地址的有效性? |
| 2 | + |
| 3 | +## 题目复现 |
| 4 | + |
| 5 | +题目:如何判断一个IP是否是合法的IP,如输入:192.168.1.0,输出:合法;输入192.168.1.1222,输出:非法。 |
| 6 | + |
| 7 | +## 考察目标 |
| 8 | +首先这个算法题目在面试中我用亲身遇到过,从面试经历中来看面试官出这道题的目的主要是为了考察对边界限制条件的考察和相关边界条件的考察,归纳一下的话就是简单的一个字符串的处理。 |
| 9 | + |
| 10 | +## 题目分析 |
| 11 | +我们应该知道IP的格式(具体呈现的规律要有一个总结,不能仅自己知道,需要具体),形式具体如下:(0~255).(0~255).(0~255).(0~255)。一共有4个数块(或者字符块)括号中给出了相关限制,然后一共有3个点(英文半角)那么由此可见可以有两种方法实现,一种是基于对字符串的处理,另一种是通过强大的正则表达式来判断,通过上面的考察目标可知面试官更倾向于你编写之前的这种,后者如果你写了只能体现你对你所使用的这种语言正则库的熟悉并不会很浓墨重彩的体现你的筛选思想 |
| 12 | + |
| 13 | +## 限制条件分析 |
| 14 | +- 输入的字符串为空则返回 false |
| 15 | +- 算上 “.” 分隔符超过了总的最大长度或者小雨最短长度返回 false |
| 16 | +- 分割后每个小块总数不等于 4 返回 false |
| 17 | +- 分割后每个小块中必须也只能是 0~9 的数字,别的字符违法 |
| 18 | +- 分割后的每个小块数值必须在 0~255 之间 |
| 19 | + |
| 20 | + |
| 21 | +## 实现代码 |
| 22 | +```c++ |
| 23 | + |
| 24 | +#include <boost/algorithm/string.hpp> |
| 25 | +#include <iostream> |
| 26 | +#include <string> |
| 27 | +#include <vector> |
| 28 | + |
| 29 | +using namespace std; |
| 30 | +using namespace boost; |
| 31 | + |
| 32 | +//字符串分割函数 |
| 33 | +// vector<string> split(string str,string pattern) |
| 34 | +// { |
| 35 | +// string::size_type pos; |
| 36 | +// vector<string> result; |
| 37 | +// str+=pattern; |
| 38 | +// int size=str.size(); |
| 39 | +// for(int i=0; i<size; i++) |
| 40 | +// { |
| 41 | +// pos=str.find(pattern,i); |
| 42 | +// if(pos<size) |
| 43 | +// { |
| 44 | +// std::string s=str.substr(i,pos-i); |
| 45 | +// result.push_back(s); |
| 46 | +// i=pos+pattern.size()-1; |
| 47 | +// } |
| 48 | +// } |
| 49 | +// return result; |
| 50 | +// } |
| 51 | +//当然这个地方自己写的分割函数肯定是没有哪些很成熟的第三方的库函数写的好的,所以这个地方的话最好还是用boost库,其中就包含有split函数,当然了如果你是用的Java写的这个面试题目那就可以直接调用库函数。 |
| 52 | + |
| 53 | +bool isIPAddressValid(const string &IPAddr) |
| 54 | +{ |
| 55 | + //限制条件1 |
| 56 | + if(IPAddr == NULL){ |
| 57 | + return false; |
| 58 | + } |
| 59 | + //限制条件2 |
| 60 | + if(IPAddr.length()<7 || IPAddr.length>15){ |
| 61 | + return false; |
| 62 | + } |
| 63 | + //限制条件3,过滤分割输入后的不正常长度 |
| 64 | + vector<string> store; |
| 65 | + spilt(store,IPAddr,is_any_of("."); |
| 66 | + if(store.size() != 4){ |
| 67 | + return false; |
| 68 | + } |
| 69 | + // vector |
| 70 | + // char* p0 = store[0].c_str(); |
| 71 | + // char* p1 = store[1].c_str(); |
| 72 | + // char* p2 = store[2].c_str(); |
| 73 | + // char* p3 = store[3].c_str(); |
| 74 | + |
| 75 | + //限制条件4,过滤输入可能是非数字字符 |
| 76 | + for(int i = 0; i < store.length(); i++){ |
| 77 | + //对分割得到的每个字符串的每个字符进行逐一判断,如果不是数字0-9,则判定为非法IP |
| 78 | + for(int j = 0; j < store[i].length(); j++){ |
| 79 | + if (store[i].c_str()[j] < '0' || arr[i].c_str()[j] > '9'){ |
| 80 | + return false; |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + //限制条件5,过滤输入的数字是否在0~255 |
| 86 | + for(int i = 0; i < store.length(); i++){ |
| 87 | + if(store[i] < "0" || store[i] > "255"){ |
| 88 | + return false; |
| 89 | + }else{ |
| 90 | + i++; |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + //如果经过前面验证都没返回到false则返回true |
| 95 | + return true; |
| 96 | +} |
| 97 | + |
| 98 | +int main(void){ |
| 99 | + string IP_arr; |
| 100 | + cin>> IP_arr; |
| 101 | + if(isIPAddressValid(IP_arr)){ |
| 102 | + cout<<"IP address is valid"<<endl |
| 103 | + }else{ |
| 104 | + cout<<"IP address is invalid"<<endl; |
| 105 | + } |
| 106 | + return 0; |
| 107 | +} |
| 108 | +``` |
| 109 | +
|
| 110 | +
|
| 111 | +## 总结 |
| 112 | +
|
| 113 | +尽管这道题目考察的是对 IP 字符串的筛选方法,但是值得注意的是这个地方的对字符串的分割十分的重要,因为一开始 C++ 并不像 Java 有这个成员函数,所以在转换的时候就是想的是分割出来的一串相邻之间用空格分开即可,但是这个就很不方便我们后面的处理了,看了第三方库函数对分割函数的处理才发现,嗯确实分割之后应该是放在已经容器当中的,这样存取方便(顿时感觉学 vector(或者说容器) 血赚)然后还有一个就是在第 4 个限制条件当编写当中时需要针对每个小块当中的数字进行分析即需要将 string 转换成为 char* 方便比较,C++ 的这个 string 这个地方就很蛋疼,别的基本上都很好理解很限制。对于正则表达式的这种写法,建议大家可以用别的语言试试,比如 Python 什么的,还是很便捷的。 |
0 commit comments