HJ18 识别有效的IP地址和掩码并进行分类统计
题目要点:#
所有的IP地址划分为 A,B,C,D,E五类:
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
私网IP范围是:
10.0.0.0~10.255.255.255
172.16.0.0~172.31.255.255
192.168.0.0~192.168.255.255
子网掩码为二进制下前面是连续的1,然后全是0。
输出:统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数
一些需要注意的细节
类似于【0...】和【127...】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时可以忽略
私有IP地址和A,B,C,D,E类地址是不冲突的,也就是说需要同时+1
如果子网掩码是非法的,则不再需要查看IP地址
全零【0.0.0.0】或者全一【255.255.255.255】的子网掩码也是非法的
思路#
- 按行读取输入,根据字符‘~’ 将IP地址与子网掩码分开
- 查看子网掩码是否合法。
- 合法,则继续检查IP地址
- 非法,则相应统计项+1,继续下一行的读入
- 查看IP地址是否合法
- 合法,查看IP地址属于哪一类,是否是私有ip地址;相应统计项+1
- 非法,相应统计项+1
具体实现#
- 判断IP地址是否合法,如果满足下列条件之一即为非法地址
- 数字段数不为4
- 存在空段,即【192..1.0】这种
- 某个段的数字大于255
- 判断子网掩码是否合法,如果满足下列条件之一即为非法掩码
- 不是一个合格的IP地址
- 在二进制下,不满足前面连续是1,然后全是0
- 在二进制下,全为0或全为1
- 如何判断一个掩码地址是不是满足前面连续是1,然后全是0?
- 将掩码地址转换为32位无符号整型,假设这个数为b。如果此时b为0,则为非法掩码
- 将b按位取反后+1。如果此时b为1,则b原来是二进制全1,非法掩码
- 如果b和b-1做按位与运算后为0,则说明是合法掩码,否则为非法掩码
代码#
#include <iostream>
#include <vector>
#include <string>
#include<sstream>
using namespace std;
bool judge_ip(string ip){
//不是合法地址:1. 不为四段 2.有空段 3.某段的数字大于255
istringstream is(ip);
string s;
vector<int> vec;
int j = 0;
while(getline(is, s,'.')){
if(++j > 4 || s.empty() || stoi(s) > 255)
return false;
}
return j == 4;
}
bool judge_mask(string mask){
istringstream is(mask);
string s;
vector<int> vec;
unsigned int j = 0;
while(getline(is, s,'.')){
j = (j << 8) + stoi(s);
}
if(!j) return false;
j = ~j + 1;
if(j == 1) return false;
if((j & (j-1)) == 0) return true;
return false;
}
bool isprivate(string ip){
istringstream is(ip);
string tmp;
vector<int> v;
while(getline(is,tmp,'.')){
v.push_back(stoi(tmp));
}
if(v[0] == 10) return true;
if(v[0] == 172 && (v[1] >= 16 && v[1] <= 31)) return true;
if(v[0] == 192 && v[1] == 168) return true;
return false;
}
int main() {
string tmp;
int a = 0,b = 0,c = 0,d = 0,e = 0,err = 0,p = 0;
while(cin >> tmp){
istringstream is(tmp);
string s;
vector<string> vec;
while(getline(is,s,'~')) vec.push_back(s);
int first = stoi(vec[0].substr(0,vec[0].find_first_of('.')));
if(first == 0 || first == 127) continue;
else if(!judge_ip(vec[1]) || !judge_mask(vec[1])) err++;
else{
if(!judge_ip(vec[0])) err++;
else{
if(isprivate(vec[0])) p++;
if(first > 0 && first <127) a++;
else if(first > 127 && first <192) b++;
else if(first > 191 && first <224) c++;
else if(first > 223 && first <240) d++;
else if(first > 239 && first <256) e++;
}
}
}
cout << a << " " << b << " " << c << " " << d << " " << e << " " << err << " " << p << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2023-04-07 617. 合并二叉树
2023-04-07 106. 从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树
2023-04-07 113. 路径总和ii
2023-04-07 112. 路径总和
2023-04-07 513. 找树左下角的值