IP地址与二进制互转
做笔试遇到了关于掩码、子网容量的相关计算,完全没概念,于是去复习
这是笔记
总得来说,掩码是因为子网划分而存在的,通过掩码可以确定一个标准网络号下的子网号,进而确定子网容量
复习完就想亲手写一个程序,完成对一个IP地址的解读和转化
- 可以复习知识点
- 下次遇到的时候可以直接用自己写的程序快速得出想要的信息,效率高
- 可以锻炼基础的编程能力
我在想,要是当初学计网、机组、特别是数据结构与算法的时候能这样做,我现在该有多大的提升呀
悟已往之不谏,知来者之可追
在写的过程中,不可避免地要实现将点分十进制的IP地址输入转换为二进制,这里有两种表示,1是以十进制整型表示,2是以01字符转的形式表示
我因为需要对二进制的每一位操作,同时也是最直接的转换思路:
- 以字符串形式整行读入
- 取出以“.”分隔的四个数字,并保存在一个int数组中
- 对每一个数字转换成8位int字符串并拼接得到最终的01字符串
这个过程中遇到了好几个字符串处理相关的函数,比如:
- 字符串转整数
stoi()
、stol()
系列 strcpy()
用来复制字符串,和c_str()
配合使用,后者用来返回当前字符串的首地址,const char*类型strtok()
用来将字符串以指定字符分隔
值得一提的是上面两个函数都遇到了不安全问题,不得不用_s的安全版本
但是得到了01字符串仍然是不够的,依旧需要十进制的二进制表示,用于运算
我用了很直接也很初级的办法,对01字符串扫描,位权相加
以下是目前的成果
#include <iostream> #include <string> #include <bitset> #include <vector> using namespace std; /* * 这是一个IP地址相关的计算器 */ // 检查IP地址是否合法 void check(string ipAddress) { } vector<int> splitIpAddress(const string& str) { vector<int> res; // if (str.empty()) return res; // 需要先将string转成char*类型 // 准备一个char数组 char* chars = new char[str.size() + 1]; // c_str返回当前字符串的首地址 // 将字符串中的每个字符拷贝到字符数组中去 strcpy_s(chars, str.size() + 1, str.c_str()); // 定义分隔符 const char* delim = "."; // 返回从头开始的被分割的字符串,没有时则返回null char* next_token = NULL; char* p = strtok_s(chars, delim, &next_token); while (p) { res.push_back(stoi(p)); p = strtok_s(NULL, delim, &next_token); } return res; } // 将点分十进制IP地址转换为32位长度的01字符串 string transferIpToString(string ipAddress) { string binaryAddress; // 将用作分隔的点去掉,返回一个4位string的数组 vector<int> nums = splitIpAddress(ipAddress); // 将4位string分别转为8位01字符串并拼接起来,返回 for (int num : nums) binaryAddress += bitset<8>(num).to_string(); return binaryAddress; } int toInt(string str) { int res = 0; // 已知这个字符串是32位长度 for (int i = 0; i < 32; i++) { if (str[i] == '1') { res += 1 << (31 - i); } } return res; } // 判断IP地址类型 char judgeType(string binaryIpAddress) { if (binaryIpAddress[0] == '0') return 'A'; else if (binaryIpAddress[1] == '0') return 'B'; else if (binaryIpAddress[2] == '0') return 'C'; else if (binaryIpAddress[3] == '0') return 'D'; else return 'E'; } void subnetting(string binaryIpAddress,string mask) { int networkNumberRow; char networkType; // 判断IP地址类型 cout << "网络地址类型为:"; if (binaryIpAddress[0] == '0') { networkType = 'A'; networkNumberRow = 8; } else if (binaryIpAddress[1] == '0') { networkType = 'B'; networkNumberRow = 16; } else if (binaryIpAddress[2] == '0') { networkType = 'C'; networkNumberRow = 24; } else if (binaryIpAddress[3] == '0') networkType = 'D'; else networkType = 'E'; cout << "网络地址类型为:" << networkType << endl; // 判断是否进行了子网划分 // 根据判断的网络类型,推出应有的网络号长度,再与与运算之后得到的作比较 // toInt(binaryIpAddress)& cout << "带子网号的网络号为:" << endl; } // 直接将IP地址转换为二进制,并以10进制整形表示 int transferIp(string ipAddress) { return 0; } int main() { // 获取输入 cout << "请输入IP地址:"<<endl; string ipAddress; getline(cin, ipAddress); cout << "请输入掩码:" << endl; string mask; getline(cin, mask); // 将点分十进制转换为32位长度的01字符串 string binaryIpAddress = transferIpToString(ipAddress); cout << "IP地址转换为二进制表示为:" << binaryIpAddress<<endl; int binaryIpAddressToInt = toInt(binaryIpAddress); cout << "十进制表示二进制IP地址为:" << binaryIpAddressToInt <<endl; // 判断IP地址类型 // 判断是否进行子网划分以及子网号是多少 return 0; }
在这一过程中我也看到了牛客网上有这一主题的题目,做IP地址点分十进制与二进制的相互转换,然后这里有一个直呼NB的写法
int main() { long long n, a1, a2, a3, a4; char ch; while (cin >> a1 >> ch >> a2 >> ch >> a3 >> ch >> a4) { cin >> n; long long res = 0; res += (a1 << 24) + (a2 << 16) + (a3 << 8) + a4; a1 = n >> 24; // 这里&255运算表示取右移后的最后8位 a2 = (n >> 16) & 255; a3 = (n >> 8) & 255; a4 = n & 255; cout << res << endl << a1 << '.' << a2 << '.' << a3 << '.' << a4 << endl; } return 0; }
- 1是没想到可以这样获取输入,直接就把分隔拆分的问题解决了
- 2是全部利用移位运算(虽然我也有使用到),短短十几行代码就把问题解决了
本文作者:YaosGHC
本文链接:https://www.cnblogs.com/yaocy/p/16700379.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步