公司 IT 防攻击小组在做一次专项分析,由于受到干扰,本应接收到的一组 ip 地址(IPv4)信息被合并成一条长信息且缺失了部分内容。
为了判断缺失情况,请你帮忙解析出字符串 str 形式的长信息中所有合法 ip 地址的个数,解析出的相同地址需要进行去重。
字符串长度 <= 100000,字符串由数字(’0’ - ‘9’)以及 ‘.’ 组成,假设 IPv4 合法地址的规则如下:
(1) 采用 "." 分隔成四个字段,每个字段采用十进制记录。
(2) 每个字段的值范围为:[0,255]。
(3) 每个字段的值除了 0 外,其他情况首位不可为 0。如:0.0.0.0 合法,0.01.0.1 不合法。
例1:
输入:str = "1.1.1111.16..172.16.254.1.1"
输出:5
解释:字符串 str 可能被分为:"172.16.254.1", "72.16.254.1", "2.16.254.1", "16.254.1.1", "6.254.1.1"
例2:
输入:str = "1.2.3.04"
输出:1
解释:字符串 str 只可能被分为 "1.2.3.0"
参考:
#include <iostream>
#include <string>
#include <regex>
#include <list>
#include <set>
using namespace std;
bool IsValidIp(string ipAddr)
{
string regStr = "^((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|[1-9])"\
"(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3})|(0.0.0.0)$";
regex regIp(regStr);
bool matchValue = regex_match(ipAddr, regIp);
return matchValue;
}
int main()
{
string inPutStr = "1.2.3.04";
// Step 1:找到所有.的位置
vector<int> vLocal;
for (int strI = 0; strI < inPutStr.length() - 1; strI++) {
if (inPutStr[strI] == '.') {
vLocal.push_back(strI);
}
}
/* 打印.位置信息 */
for (int debugI = 0; debugI < vLocal.size(); debugI++) {
cout<<vLocal[debugI]<<",";
}
cout<<inPutStr.size()<<","<<inPutStr.length()<<","<<endl;
set<string> ipSet;
// Step 2:按照.的位置进行遍历
for (vector<int>::iterator it = vLocal.begin(); it != vLocal.end(); it++) {
cout<<"*it is "<<*it<<endl;
// .的位置不合法,或者连续出现2个.
if (((*(it + 2) - *(it + 1)) < 1) || ((*(it + 1) - *(it)) < 1) ||
(*(it + 2) == (inPutStr.length() - 1)) || (*(it) == 0)) {
cout<<*it<<"is unvalid"<<endl;
continue;
}
int left = *it - 1; // 左边偏移1位
int right = *(it + 2) + 1; // 右边第三个分隔符偏移1位
string ipAddrTemp = inPutStr.substr(left, (right - left + 1));
bool matchR = IsValidIp(ipAddrTemp);
cout<<"[1]left is "<<left<<", right is "<<right<<", str is "<<ipAddrTemp<<", matchR is"<<matchR<<endl;
// Step 3:如果是合法的地址,则根据合法地址进行前后探索
if (matchR) {
for (int i = right; i <= (right + 2) && (i < inPutStr.size()); i++) {
for (int j = left; (j >= (left - 2) && (j >= 0)); j--) {
ipAddrTemp = inPutStr.substr(j, i - j + 1);
matchR = IsValidIp(ipAddrTemp);
cout<<"[2]left ="<<left<<", right ="<<right<<", str is "<<ipAddrTemp<<", matchR is"<<matchR<<endl;
if (matchR) {
ipSet.insert(ipAddrTemp);
}
}
}
}
}
for (set<string>::iterator itStr = ipSet.begin(); itStr != ipSet.end(); itStr++) {
cout<<"Valid IpAddr "<<*itStr<<endl;
}
cout<<"Total IP is"<<ipSet.size()<<endl;
return 0;
}
看到别人的解答中,用到了正则表达式,这个还是挺巧妙的。关于正则表达式的基本使用,参考一下:https://www.zhihu.com/question/48219401/answer/742444326
