题解 | #判断两个IP是否属于同一子网#
判断两个IP是否属于同一子网
https://www.nowcoder.com/practice/34a597ee15eb4fa2b956f4c595f03218
重要的是掩码连续为1然后连续为0的判断,需要位运算,准则为:
- 将掩码地址转换为32位无符号整型,假设这个数为b。如果此时b为0,则为非法掩码
- 将b按位取反后+1。如果此时b为1,则b原来是二进制全1,非法掩码
- 如果b和b-1做按位与运算后为0,则说明是合法掩码,否则为非法掩码
#include <bits/stdc++.h> using namespace std; vector<int> vpm; vector<int> vpi; vector<int> vpi2; bool check_mask(string x) { int i = 0; int j = 0; while (i < x.size() and j < x.size()) { while (i < x.size() and !isdigit(x[i])) { if (x[i] != '.') return false; j = ++i; } while (j < x.size() and isdigit(x[j])) j++; int tt = stoi(x.substr(i, j - i)); if (tt < 0 or tt > 255) return false; vpm.push_back(tt); i = ++j; } if (vpm.size() != 4) return false; unsigned b = 0; for (int x : vpm) { b = (b << 8) + x; } if (b == 0) return false; if (~b + 1 == 1) return false; b = ~b + 1; if ((b & (b - 1)) == 0) return true; return false; } bool check_ip(string x) { int i = 0; int j = 0; while (i < x.size() and j < x.size()) { while (i < x.size() and !isdigit(x[i])) { if (x[i] != '.') return false; j = ++i; } while (j < x.size() and isdigit(x[j])) j++; int tt = stoi(x.substr(i, j - i)); if (tt < 0 or tt > 255) return false; vpi.push_back(tt); i = ++j; } if (vpi.size() != 4) return false; return true; } bool check_ip2(string x) { int i = 0; int j = 0; while (i < x.size() and j < x.size()) { while (i < x.size() and !isdigit(x[i])) { if (x[i] != '.') return false; j = ++i; } while (j < x.size() and isdigit(x[j])) j++; int tt = stoi(x.substr(i, j - i)); if (tt < 0 or tt > 255) return false; vpi2.push_back(tt); i = ++j; } if (vpi2.size() != 4) return false; return true; } int main() { string c, a, b; while (cin >> c >> a >> b) { // 注意 while 处理多个 case vpi.clear(); vpm.clear(); vpi2.clear(); if (check_mask(c) and check_ip(a) and check_ip2(b)) { bool flag = true; for(int i = 0; i < 4; i++){ if((vpm[i] & vpi[i]) != (vpm[i] &vpi2[i])){ flag = false; break; } } if (flag) cout << "0" << endl; else cout << "2" << endl; } else cout << "1" << endl; } return 0; } // 64 位输出请用 printf("%lld")