识别有效的IP地址和掩码并进行分类统计
在本题中,我们需要处理地址信息,其由 IP 地址和子网掩码组成,这两者均形如 "*.*.*.*"
,由四段数字组成,每段数字之间以点分隔。
我们定义五类 IP 地址:
- A类:”1.0.0.0”-“126.255.255.255”;
- B类:”128.0.0.0”-“191.255.255.255”;
- C类:”192.0.0.0”-“223.255.255.255”;
- D类:”224.0.0.0”-“239.255.255.255”;
- E类:”240.0.0.0”-“255.255.255.255”。
我们定义私有 IPIP 地址:
- “10.0.0.0”-“10.255.255.255”;
- “172.16.0.0”-“172.31.255.255”;
- “192.168.0.0”-“192.168.255.255”。
我们定义合法的子网掩码:
- 将 IP 地址转换为二进制后,必须由若干个连续的 1 后跟若干个连续的 0 组成;
- 例如,”1.1.1.5” 是一个非法的子网掩码,因为它转换为二进制后为 1.1.1.101 ,中间出现了 0 后又出现了 1 ;
- 注意,全为 1 或全为 0 的子网掩码也是非法的。
现在,你需要分类统计ABCDE类地址的数量、错误 IP 或错误子网掩码的数量、私有 IP 的数量。
特别地,我们还有以下提示:
- 类似于
"0.*.*.*"
和"127.*.*.*"
的 IP 地址不属于上述输入的任意一类,也不属于不合法 IP 地址; - 一个 IP 地址既可以是私有 IP 地址,也可以是五类 IP 地址之一,计数时请分别计入。
输入描述:
本题将会给出 1≦T≦1000 条地址信息,确切数字未知,您需要一直读入直到文件结尾;每条地址信息描述如下:
在一行上先输入一个字符串,代表 IP 地址;随后,在同一行输入一个字符串,代表子网掩码;使用 “~” 分隔。
输出描述:
在一行上输出七个整数,分别代表ABCDE类地址的数量、错误 IP 或错误子网掩码的数量、私有 IP 的数量。
示例1
输入:
1 | 10.70.44.68~1.1.1.5 |
输出:
1 | 1 0 1 0 0 2 1 |
说明:
1 | 对于第一条地址信息,"10.70.44.68""10.70.44.68" 是其 IPIP 地址,"255.254.255.0""255.254.255.0" 是其子网掩码;该条地址的子网掩码非法。 |
示例2
输入:
1 | 0.201.56.50~255.255.255.0 |
输出:
1 | 0 0 0 0 0 0 0 |
说明:
1 | 对于第一、二条地址信息,均属于上方提示中提到的特殊 IPIP 地址,不需要处理,直接跳过。 |
问题分析
- IPv4 地址点分十进制表示形如
129.244.251.53
,共有4个字段,中间由点隔开。每个字段的值是 0 ~ 255 共 256 个值,每个值可以保存在一个字节中(unsigned char)。sizeof(int) 等于 4个 字节,所以可以将一个 IP 地址转换成一个 unsigned int 数值。 - A 类地址段
"1.0.0.0"-"126.255.255.255"
,值的范围为. - A类地址范围包含了一段私有地址段
"10.0.0.0"-"10.255.255.255"
,其值对应的范围为:.
- A类地址范围包含了一段私有地址段
- B类地址段
"128.0.0.0"-"191.255.255.255"
,值的范围为. - B类地址中包含了一段私有地址段
"172.16.0.0"-"172.31.255.255"
,值的范围.
- B类地址中包含了一段私有地址段
- C类地址段
"192.0.0.0"-"223.255.255.255"
,. - C类地址段中包含了一段私有地址
"192.168.0.0"-"192.168.255.255"
,.
- C类地址段中包含了一段私有地址
- D类
"224.0.0.0"-"239.255.255.255"
,. - E类,题目中的描述的地址段是
"240.0.0.0"-"255.255.255.255"
,根据计算机网络的知识,255.255.255.255
是一个特殊的 广播地址,专门用于局域网中的广播通信,不算是 E 类IP地址。所以数值范围是左闭右开的. - 根据题意,只有子网掩码合法的情况下,才对IP地址进行判断是否合法和分类。
- 根据题意,
0.*.*.*
和127.*.*.*
地址段,无论子网掩码是否合法都不列统计范围。
算法设计思路
写一个函数 unsigned int strToIP(char* ipstr);
,可以将字符串的 IP 地址或子网掩码转换成一个 unsigned int 型的数值。如果 IP 地址格式错误返回 -1 。 (-1 的补码为 1111 1111 1111 1111 1111 1111 1111 1111
对应了 255.255.255.255
的地址)。
写一个函数 int isCorrectSubnetMask(unsigned int subnet_mask);
,用于判断子网掩码是否合法,合法返回 1,否则返回 0 。
strToIP
函数的实现:
1 | unsigned int strToIP(char* ipstr) { // 形如"192.168.233.12."的IP地址字符串转换成数值 |
isCorrectSubnetMask
函数的实现:
1 | int isCorrectSubnetMask(unsigned int subnet_mask) { //判断子网掩码是否合法,合法返回1,不合法返回0 |
完整代码:
1 |
|
提交代码:过辣!!!
改进一下输入部分,使用 fgets()
,在输入一行的时候就进行统计操作,不用保存所有数据,更节省内存,同时少了 for 循环遍历。如下:
1 | int main() { |