本题涉及很多字符串的处理,进制转换的处理,以及IP地址和子网掩码的判别问题,综合性较强。
# include <iostream>
# include <string>
# include <vector>
# include <sstream>
# include <cmath>
using namespace std;
// 用于分割地址中各段的字符串
vector<string> get_string(string s) {
istringstream is(s);
string seg;
vector<string> res;
while (getline(is, seg, '.')) {
res.push_back(seg);
}
return res;
}
// 判断IP地址是否合法
bool judge_IP(string s) {
vector<string> IP = get_string(s);
int k = 0;
for (vector<string>::iterator iter = IP.begin(); iter != IP.end(); iter++) {
auto seg = *iter;
k++;
if (seg == " ") return false;
else {
if (stoi(seg) > 255) return false;
if (stoi(seg) < 0) return false;
}
}
if (k == 4) return true;
else return false;
}
// 判断子网掩码地址是否合法
bool judge_mask(string s) {
vector<string> mask = get_string(s);
unsigned b = 0;
for (vector<string>::iterator iter = mask.begin(); iter != mask.end(); iter++) {
auto seg = *iter;
if (seg == " ") return false;
else {
// 将子网掩码地址转换为32位无符号整形
b = (b << 8) + stoi(seg);
}
}
if (!b) {
return false; // b为零,非法
}
b = ~b + 1;
if (b == 1) {
return false; // b按位取反后加一,如果此时b为1,则b原来是二进制全一,非法
}
if ((b & (b - 1)) == 0) {
return true; // b和b-1按位运算后为0,合法
}
return false;
}
// 将十进制转换为二进制
vector<string> dec_bin(vector<string> dec) {
vector<string> res;
for (vector<string>::iterator iter = dec.begin(); iter != dec.end(); iter++) {
int val = stoi(*iter);
string s;
int rem = val % 2;
val /= 2;
s = s + to_string(rem);
while (val != 0) {
rem = val % 2;
val /= 2;
s = s + to_string(rem);
}
string s_reverse;
if (s.size() != 8) {
// 不足8位
int num = 8 - s.size();
for (int k = 0; k < num; k++) {
s_reverse = s_reverse + "0";
}
}
for (int j = s.size() - 1; j >= 0; j--) {
s_reverse = s_reverse + s[j];
}
res.push_back(s_reverse);
}
return res;
}
//将二进制转换为十进制
vector<int> bin_dec(vector<string> s) {
vector<int> dec;
int sum = 0;
for (vector<string>::iterator iter = s.begin(); iter != s.end(); iter++) {
string temp = *iter;
for(int i = temp.size() - 1; i >= 0; i--) {
sum += stoi(string(1, temp[i])) * pow(2, temp.size() - 1 - i);
}
dec.push_back(sum);
sum = 0;
}
return dec;
}
// 判断两个IP地址是否在同一个子网中
bool judge_IP_isSame(string mask, string IP1, string IP2) {
vector<string> v_mask_temp = get_string(mask);
vector<string> v_IP1_temp = get_string(IP1);
vector<string> v_IP2_temp = get_string(IP2);
// 将十进制转换为二进制
vector<string> v_mask = dec_bin(v_mask_temp);
vector<string> v_IP1 = dec_bin(v_IP1_temp);
vector<string> v_IP2 = dec_bin(v_IP2_temp);
// 合成二进制
string mask_bin, IP1_bin, IP2_bin;
for (int i = 0; i < 4; i++) {
mask_bin = mask_bin + v_mask[i];
IP1_bin = IP1_bin + v_IP1[i];
IP2_bin = IP2_bin + v_IP2[i];
}
// 两个二进制取与操作
string AND1, AND2;
for (int i = 0; i < 32; i++) {
if (mask_bin[i] == '1' && IP1_bin[i] == '1') AND1 = AND1 + "1";
else AND1 = AND1 + "0";
if (mask_bin[i] == '1' && IP2_bin[i] == '1') AND2 = AND2 + "1";
else AND2 = AND2 + "0";
}
// 拆分为四段字符串
vector<string> AND1_seg, AND2_seg;
for (int i = 0; i < 4; i++) {
AND1_seg.push_back(AND1.substr(i * 8, 8));
AND2_seg.push_back(AND2.substr(i * 8, 8));
}
// 二进制转换为十进制(这一步其实不用转换,直接比较二进制就可以了)
vector<int> AND1_dec, AND2_dec;
AND1_dec = bin_dec(AND1_seg);
AND2_dec = bin_dec(AND2_seg);
// 判断是否相等
for (int i = 0; i < 4; i++) {
if (AND1_dec[i] != AND2_dec[i]) return false;
}
return true;
}
int main(){
string mask, IP1, IP2;
getline(cin, mask, '\n');
getline(cin, IP1, '\n');
getline(cin, IP2, '\n');
// 判断地址是否非法
if (!judge_mask(mask) || !judge_IP(IP1) || !judge_IP(IP2)) {
cout << "1" << endl;
} else {
if (judge_IP_isSame(mask, IP1, IP2)) {
// 两个IP属于同一个网络
cout << "0" << endl;
} else {
// 两个IP不属于同一个网络
cout << "2" << endl;
}
}
return 0;
}

京公网安备 11010502036488号