UVa 1590 IP Networks (IP网络)

来源:互联网 发布:gitbook 绑定域名 编辑:程序博客网 时间:2024/05/18 00:15


题意:

子网掩码是子网划分的依据,它跟IP地址一样,长度也是32位,点分十进制表示,每部分0~255,但是跟IP地址不同的是,子网掩码只能由连续的1和0组成,也就是说,把这32位从任意位置分开,左边只能全是1,右边只能全是0。比如11111111.11111111.11111111.11111000(255.255.255.248)就是合法的子网掩码,而11000000.10101000.00000001.00000000(192.168.1.0)就不合法。

给定两个IP,假设其子网掩码二进制有x个连续的1,则如果这两个IP的二进制前x位对应相等,那么这两个IP就属于同一网段,也就是属于同一个子网。

输入一些IP地址,求最小的网络(即包含IP地址最少的网络),包含所有这些输入地址。

例如:若输入三个IP地址:194.85.160.177、 194.85.160.183、 194.85.160.178,包含上述三个地址的最小网络的网络地址为194.85.160.176,子网掩码是255.255.255.248


思路:

十进制--->二进制--->十进制

由二进制可以得到公共的二进制表示,则子网掩码就是将这些公共部分全部用1表示,剩余右边全用0补。而最小地址则是公共范围相同,剩余右边全用0补。

十进制和二进制的切割转化,可以用sscanf函数和sprintf函数


下面代码部分注释是为了辅助调试 :)

#include <stdio.h>#include <string.h>#include <math.h>#define maxn 1010char s[maxn][35],s1[4][10], s2[20];char q[35], w[4][10], mins[35];char z[35], h[4][10], ans[35];int a[4],d1[4],d2[4];int m;void num_to_str(int n, char b[]){//将整数转换成相应的二进制字符串int k = 8;b[k--] = '\0';while (k>=0){b[k] = n % 2 + '0';n /= 2;k--;}}int compare(char x[], char y[], int n)//比较两个字符串的前n个字符返回从第一个不同的字符的前一个位置,完全相同返回n{int i;for ( i = 0;i <= n;i++)if (x[i] != y[i]) break;return (i - 1);}int str_to_num(char d[]){//将二进制字符串转换成对应整数int res = 0;for (int i = 0;i < 8;i++)res = res * 2 + d[i] - '0';return res;}int main(){//freopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);while (~scanf("%d", &m)){for (int i = 0;i < m;i++){scanf("%s", s2);for (int j = 0;s2[j];j++)if (s2[j] == '.') s2[j] = ' ';//puts(s2);sscanf(s2, "%d %d %d %d", &a[0], &a[1], &a[2], &a[3]);//printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]);for (int j = 0;j < 4;j++){num_to_str(a[j], s1[j]);//printf("%s ", s1[j]);if (j) strcat(s[i], s1[j]);else strcpy(s[i], s1[j]);//转化成二进制形式IP地址}//putchar('\n');//puts(s[i]);}int r = 31;for (int i = 0;i < m - 1;i++)r = compare(s[i], s[i + 1],r);//寻找相同的位数int l = 0;for (int j = 0;j<=31;j++){if (j <= r) q[l++] = s[0][j];else q[l++] = '0';if ((j + 1) % 8 == 0 && j < 31) q[l++] = ' ';}//puts(q);sscanf(q, "%s %s %s %s", w[0], w[1], w[2], w[3]);for (int j = 0;j < 4;j++)d1[j]=str_to_num(w[j]);sprintf(mins, "%d.%d.%d.%d", d1[0], d1[1], d1[2], d1[3]);//转化成十进制形式IP地址int f = 0;for (int j = 0;j <= 31;j++){if (j <= r) z[f++] = '1';else z[f++] = '0';if ((j + 1) % 8 == 0 && j<31) z[f++] = ' ';}//puts(z);sscanf(z, "%s %s %s %s", h[0],h[1], h[2], h[3]);for (int j = 0;j < 4;j++)d2[j]=str_to_num(h[j]);sprintf(ans, "%d.%d.%d.%d", d2[0], d2[1], d2[2], d2[3]);puts(mins);puts(ans);}return 0;}


0 0
原创粉丝点击