当前位置: 首页 > news >正文

算法题——IP地址分类与子网掩码

从零教你识别有效IP地址和子网掩码并分类

一、题目背景

在计算机网络中,IP地址(IPv4)是用来标识设备的,就像每个房子都有自己的门牌号一样。
而子网掩码(Subnet Mask)是用来划分“街道”和“房子”的边界的。
这道题让我们给定很多行数据,每行都是:

IP地址~子网掩码

比如:

192.168.0.2~255.255.255.0
10.70.44.68~255.0.0.0
1.0.0.1~255.0.0.0

要求:

  1. 判断IP和掩码是否合法
  2. 根据IP地址的第一段,把它分成 A / B / C / D / E 类
  3. 统计私有IP的数量
  4. 统计非法地址的数量

二、网络基础小课堂

1. IPv4地址格式

IPv4长这样:

192.168.0.1
  • 一共有4段数字
  • 每段数字范围是 0 ~ 255
  • .分隔
  • 本质是 32位二进制,每段是8位

例:

192.168.0.1
= 11000000.10101000.00000000.00000001

2. IP地址的五大类

用第一段数字判断:

类别第一段范围(十进制)用途
A类1 ~ 126大型网络
B类128 ~ 191中型网络
C类192 ~ 223小型网络
D类224 ~ 239多播
E类240 ~ 255保留

注意:

  • 127.x.x.x回环地址(测试用,不分类)
  • 0.x.x.x 是非法地址

3. 私有IP地址(内网)

这些是家里路由器常用的地址,不能直接访问互联网:

  • A类私有:10.0.0.0 ~ 10.255.255.255
  • B类私有:172.16.0.0 ~ 172.31.255.255
  • C类私有:192.168.0.0 ~ 192.168.255.255

4. 子网掩码

子网掩码也是4段数字,比如:

255.255.255.0

作用是告诉计算机IP地址的哪部分是网络号,哪部分是主机号

合法掩码的二进制必须是:

  • 前面全是1
  • 后面全是0
  • 不能中间夹杂“1010”这种乱序

例:

255.255.255.0
= 11111111.11111111.11111111.00000000 ✅合法255.0.255.0
= 11111111.00000000.11111111.00000000 ❌非法

三、解题步骤

步骤1:拆分IP和掩码

输入:

192.168.0.1~255.255.255.0

先用 ~ 分开:

  • 左边是IP地址
  • 右边是掩码

步骤2:把每段数字提取出来

比如:

192.168.0.1 → [192, 168, 0, 1]

这样后面就能直接用数字判断范围了。


步骤3:判断掩码是否合法

规则:

  1. 不能全0:0.0.0.0
  2. 不能全255:255.255.255.255
  3. 二进制必须是前面全1,后面全0

做法:

  • 把掩码转成一个32位整数
  • 检查它的二进制是否符合111...000...模式

步骤4:判断IP是否合法

  • 必须是 4 段数字
  • 每段 0~255
  • 第一段不能是0或127

步骤5:分类

用第一段数字判断是 A/B/C/D/E 类,并计数。


步骤6:判断是否是私有IP

  • 第一段是 10 → A类私有
  • 第一段是 172 且第二段 16~31 → B类私有
  • 第一段是 192 且第二段是 168 → C类私有

四、完整代码(小白版+行级注释)

#include <iostream>
#include <vector>
#include <string>
using namespace std;// 字符串转数字数组,比如 "192.168.0.1" -> [192,168,0,1]
vector<int> strToIP(const string &s) {vector<int> res;string num;for (char c : s) {if (c == '.') {res.push_back(stoi(num)); // 转成整数并存到数组num.clear();              // 清空临时字符串} else {num.push_back(c);         // 累加数字字符}}res.push_back(stoi(num));         // 最后一段数字也要加进去return res;
}// 判断掩码是否合法
bool isValidMask(vector<int> mask) {if (mask.size() != 4) return false;unsigned int m = 0;for (int n : mask) {if (n < 0 || n > 255) return false; // 范围检查m = (m << 8) | n;                   // 拼成32位整数}if (m == 0 || m == 0xFFFFFFFF) return false; // 全0或全1非法// 检查是否是111...000...模式unsigned int t = ~m + 1;return (t & (t - 1)) == 0;
}// 判断IP是否合法
bool isValidIP(vector<int> ip) {if (ip.size() != 4) return false;for (int n : ip) {if (n < 0 || n > 255) return false;}if (ip[0] == 0 || ip[0] == 127) return false;return true;
}int main() {string line;// 分类计数int A = 0, B = 0, C = 0, D = 0, E = 0;int error = 0, privateIP = 0;while (getline(cin, line)) { // 一行一行读size_t pos = line.find('~');if (pos == string::npos) continue;string ipStr = line.substr(0, pos);string maskStr = line.substr(pos + 1);vector<int> ip = strToIP(ipStr);vector<int> mask = strToIP(maskStr);// 判断合法性if (!isValidMask(mask) || !isValidIP(ip)) {error++;continue;}// 分类if (ip[0] >= 1 && ip[0] <= 126) A++;else if (ip[0] >= 128 && ip[0] <= 191) B++;else if (ip[0] >= 192 && ip[0] <= 223) C++;else if (ip[0] >= 224 && ip[0] <= 239) D++;else if (ip[0] >= 240 && ip[0] <= 255) E++;// 私有IP判断if (ip[0] == 10) privateIP++;else if (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) privateIP++;else if (ip[0] == 192 && ip[1] == 168) privateIP++;}// 输出结果cout << A << " " << B << " " << C << " " << D << " " << E << " " << error << " " << privateIP << endl;return 0;
}

五、运行示例

输入:

10.70.44.68~255.0.0.0
1.0.0.1~255.0.0.0
192.168.0.2~255.255.255.0
127.0.0.1~255.0.0.0
0.201.56.50~255.255.255.0

输出:

2 0 1 0 0 2 2

解释:

  • A类:1.0.0.110.70.44.68
  • C类:192.168.0.2
  • 错误:127.0.0.1(回环),0.201.56.50(首段为0)
  • 私有IP:10.70.44.68(A类私有),192.168.0.2(C类私有)

六、总结

  • 本题考察字符串处理+网络基础+逻辑判断
  • 小白需要特别注意掩码的合法性判断
  • 推荐用二进制思路检查掩码,因为更简单、准确
http://www.dtcms.com/a/326778.html

相关文章:

  • CobaltStrike安装和使用教程
  • Cobalt Strike的搭建和使用
  • JDK21虚拟线程和 Golang1.24协程的比较
  • STM32——system文件夹
  • Empire--安装、使用
  • 集团型企业如何统一管控子公司权限?
  • 奈飞工厂:算法优化实战​
  • 视频播放器哪个好用?视频播放器PotPlayer,KMP Player
  • 多轮会话记忆的核心挑战
  • 8.11下一代防火墙组网方案笔记
  • 使用MAS(Microsoft Activation Scripts)永久获得win10专业版和office全套
  • C++算法·前缀和
  • DCN之AP IGMP Snooping 原理与配置
  • P3917 异或序列 题解
  • Day01_QT编程20250811
  • while循环结合列表或字典
  • 二叉搜索树解析与实现
  • 快速设计简单嵌入式操作系统(3):动手实操,基于STC8编写单任务执行程序,感悟MCU指令的执行过程
  • USB 标准请求
  • 机器学习——KMeans聚类实战案例解析
  • git配置proxy
  • Docker-09.Docker基础-Dockerfile语法
  • Docker中部署安装MySQL 5.7.32的详细过程
  • Rust面试题及详细答案120道(19-26)-- 所有权与借用
  • PTE之路--04文
  • java面试题准备
  • 【k近邻】Kd树的构造与最近邻搜索算法
  • 线程池知识点总结
  • Spring Cloud Gateway 路由与过滤器实战:转发请求并添加自定义请求头(最新版本)
  • 【QT】UI 开发全攻略:打造专业级跨平台界面