【华为od刷题(C++)】HJ33 整数与IP地址间的转换

我的代码:

#include 
//这个头文件提供了输入输出流的功能,使得我们能够使用 cin 和 cout 来进行输入输出
using namespace std;
//可以直接使用标准命名空间 std 中的功能
//比如 cout 和 cin,而不需要每次都写出 std::

int main() {
    long long int a, b, c, d;
    //a, b, c, d:这四个变量用来存储IP地址的四个部分
    //分别代表IP地址中的四个字节

    long long int num;
    // 输入IP和十进制数字

    //num:这个变量用来存储一个32位的十进制数字
    //它是通过将IP地址四个字节拼接在一起得到的

    scanf("%lld.%lld.%lld.%lld %lld", &a, &b, &c, &d, &num);
    // 输出十进制数字num

    /*scanf 用来从标准输入中读取数据
    
    这里使用的格式是:"%lld.%lld.%lld.%lld%lld",
    它读取一个IP地址和一个十进制数字

    %lld 用来读取 long long int 类型的数据,适合处理较大的整数

    "." 是格式化字符串的一部分,它是用来匹配输入中的点号 .
    (分隔每个IP地址的字节)*/

    cout << (a << 24) + (b << 16) + (c << 8) + d << endl;
    // 输出IP

    /*这段代码将IP地址的四个部分 (a, b, c, d) 转换为一个32位的十进制数字
    转换的方法是通过位移操作:

    a << 24:将 a 左移24位,将其放到高字节
    例如,如果 a = 192,那么 a << 24 就会变成 192 << 24,
    结果是 192 * 2^24,即 192 位于数字的第一个字节

    b << 16:将 b 左移16位,放到次高字节
    例如,如果 b = 168,那么 b << 16 就会变成 168 * 2^16,即 168 位于数字的第二个字节

    c << 8:将 c 左移8位,放到次低字节
    例如,如果 c = 1,那么 c << 8 就会变成 1 * 2^8,即 1 位于数字的第三个字节

    d:d 保持不变,放到低字节
    例如,如果 d = 1,那么 d 就是IP地址的最后一个字节

    通过加法将这些结果加起来,得到最终的十进制数 num

    例如,IP地址 192.168.1.1 将被转换为 3232235777*/

    cout << ((num >> 24) & 0xff) << '.' << ((num >> 16) & 0xff) << '.' << ((num >> 8) & 0xff) << '.' << (num & 0xff);
    /*这段代码将 num 转换回IP地址

    为了从32位数字中提取出每个字节,使用了右移和按位与操作:

    (num >> 24) & 0xff:先将 num 右移24位,得到最高字节,
    然后通过与操作 & 0xff 保留低8位,得到IP地址的第一个字节

    (num >> 16) & 0xff:将 num 右移16位,得到次高字节,
    经过与操作后得到第二个字节

    (num >> 8) & 0xff:将 num 右移8位,得到次低字节,
    经过与操作后得到第三个字节

    num & 0xff:直接通过与操作 & 0xff 提取低字节,得到IP地址的最后一个字节
    
    然后通过 cout 输出这些字节,用 . 分隔开,形成正确的IP地址格式*/

      return 0;
}

这段代码的功能是进行IP地址和十进制数字之间的转换;它能够将一个IP地址转换为其对应的十进制数,同时也能够将一个十进制数转换回IP地址

IP地址的表示

IP地址通常由四个字节(8位)组成,每个字节的值在0到255之间;比如,IP地址 192.168.1.1 可以被表示为:

  • a = 192
  • b = 168
  • c = 1
  • d = 1

这四个字节合起来构成一个32位的整数

位移操作

(a << 24) + (b << 16) + (c << 8) + d;

这里的目的是将四个字节按照IP地址的顺序合并成一个32位的整数;具体来说:

  • (a << 24):将 a 左移24位,使得 a 的值处于32位数的最高字节;例如,如果 a = 192,那么 a << 24 就会变成 192 << 24,结果是 192 * 2^24,即 192 位于数字的第一个字节

  • (b << 16):将 b 左移16位,b 的值变成次高字节;例如,如果 b = 168,那么 b << 16 就会变成 168 * 2^16,即 168 位于数字的第二个字节

  • (c << 8):将 c 左移8位,c 的值变成次低字节;例如,如果 c = 1,那么 c << 8 就会变成 1 * 2^8,即 1 位于数字的第三个字节

  • dd 不需要左移,直接作为最低字节。例如,如果 d = 1,那么 d 就是IP地址的最后一个字节

整体加法

这些通过左移操作得到的值会被加起来:

  • a << 24:将 a 移到32位整数的最左侧
  • b << 16:将 b 移到次左侧
  • c << 8:将 c 移到次右侧
  • d:保持在最右侧

将这些值加起来,得到一个表示整个IP地址的32位整数

例子

假设输入的IP地址是 192.168.1.1,则:

  • a = 192
  • b = 168
  • c = 1
  • d = 1

我们进行计算:

  • (a << 24) = 192 << 24 = 192 * 2^24 = 3221225472
  • (b << 16) = 168 << 16 = 168 * 2^16 = 11010048
  • (c << 8) = 1 << 8 = 1 * 2^8 = 256
  • d = 1

将这些值加起来:

3221225472 + 11010048 + 256 + 1 = 3232235777

输出

输出的结果会是 3232235777,这是IP地址 192.168.1.1 转换成的十进制数

总结

这行代码的作用是将四个字节的IP地址(a, b, c, d)通过位移和加法操作,拼接成一个32位的十进制整数;这个整数就是IP地址对应的十进制值

num 是一个32位整数,表示一个 IP 地址,例如 3232235777,对应的IP地址是 192.168.1.1

cout << ((num >> 24) & 0xff) << '.'
     << ((num >> 16) & 0xff) << '.' 
     << ((num >> 8) & 0xff) << '.' 
     << (num & 0xff);

1. (num >> 24) & 0xff

  • num >> 24 将 num 右移24位,目的是将高8位移到最低8位的位置
    • 例如,如果 num = 3232235777(即 192.168.1.1),则右移24位后,num 的值变成了 192(即 IP 地址的第一个字节)
  • & 0xff 使用位掩码 0xff (即 11111111,十六进制表示) 将只保留右移后的最低8位,即第一个字节
    • 192 & 0xff 结果是 192

2. (num >> 16) & 0xff

  • num >> 16 将 num 右移16位,目标是将第二个字节移到最低字节的位置
    • 对于 3232235777(即 192.168.1.1),右移16位后,得到 168
  • & 0xff 保证只保留最低的8位(即第二个字节),所以 168 & 0xff 结果是 168

3. (num >> 8) & 0xff

  • num >> 8 将 num 右移8位,目标是将第三个字节移到最低字节的位置
    • 对于 3232235777(即 192.168.1.1),右移8位后,得到 1
  • & 0xff 保证只保留最低的8位,所以 1 & 0xff 结果是 1

4. (num & 0xff)

  • num & 0xff 用来获取 num 的最低8位,即第四个字节
    • 对于 3232235777(即 192.168.1.1), num & 0xff 结果是 1

输出格式

这些操作将分别提取 num 的四个字节,并以点 . 作为分隔符连接起来,最终输出的结果会是:

192.168.1.1

总结

这段代码的功能是将一个32位的整数 num 转换为对应的 IP 地址格式(点分十进制形式),通过逐字节提取并输出每个字节的值,使用 . 作为分隔符

你可能感兴趣的:(华为od,c++,链表)