这道题先求出子网掩码,然后将最小的IP地址与子网掩码按位与即可得到网络地址。注意以下问题:
1.求子网掩码,即所有32位地址最左一个不同出现的地方后全为0,前面全为1。
2.由于IP地址可能有重复,可以用set来保存所有IP地址,从而去除重复。
3.只需要将最小的IP地址与子网掩码按位与即可得到网络地址,set里面是按字典序排的,从而只需要取set第一个IP地址即可。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>
#include<cstring>
#include<string>
using namespace std;
int a[4];
int b[32];
int c[4];
int d[32];
int ans;
int n;
set<string> s;
void init(){
memset(b, 0, sizeof(b));
for (int i = 0; i < 4; i++){
a[i] = 255;
}
s.clear();
ans = 33;
}
bool getInput(int a[]){
string str;
cin >> str;
if (s.count(str))
return false;
s.insert(str);
int i = 0;
int cnt = 0;
while (str[i] != '\0'){
int t = 0;
while (str[i] != '.' && str[i]!='\0'){
t = t * 10 + (str[i] - '0');
i++;
}
a[cnt++] = t;
if (str[i] == '\0')
break;
i++;
}
return true;
}
void convert(){
int t[4];
memcpy(t, c, sizeof(c));
for (int i = 0; i < 4; i++){
for (int j = 0; j < 8; j++){
d[i * 8 +7-j] = t[i]&1;
t[i] = t[i] >> 1;
}
}
if (ans == 33){
memcpy(b, d, sizeof(d));
ans = 32;
return;
}
int i;
for (i = 0; i < ans; i++){
if (d[i] != b[i])
break;
}
if (i < ans)
ans = i;
}
int myprint(int x){
int t = 0;
for (int i = 0; i < 8; i++)
t = t * 2 + b[i+x];
return t;
}
void print(){//最终b存放子网掩码地址,a存放网络地址
memset(b, 0, sizeof(b));
for (int i = 0; i < ans; i++)
b[i] = 1;
for (int i = 0; i < 4; i++){
c[i] = myprint(i * 8);
}
string str = *(s.begin());
int i = 0;
int cnt = 0;
while (str[i] != '\0'){
int t = 0;
while (str[i] != '.' && str[i] != '\0'){
t = t * 10 + (str[i] - '0');
i++;
}
a[cnt++] = t;
if (str[i] == '\0')
break;
i++;
}
for (int i = 0; i < 4; i++)
a[i] = a[i] & c[i];
for (int i = 0; i < 4; i++){
if (i)
cout << ".";
cout << a[i];
}
cout << endl;
for (int i = 0; i < 4; i++){
if (i)
cout << ".";
cout << c[i];
}
cout << endl;
}
int main()
{
int m;
while (cin >> m){
init();
n = 0;
for (int i = 0; i < m; i++){
if (!getInput(c))
continue;
convert();
}
print();
}
return 0;
}