每日一题:1、虚拟IPv4地址转换为32位整数(JS)

题目背景

我们需要处理一种特殊的虚拟IPv4地址,这种地址由4个小节组成,每节之间用#分隔。与标准IPv4地址不同,虚拟IPv4地址的第一节范围是1~128,后三节的范围是0~255。我们需要将这种虚拟IPv4地址转换为一个唯一的32位整数。如果输入的地址不合法,则返回invalid IP

输入输出
  • ​输入​​:一行字符串,表示虚拟IPv4地址,例如128#0#255#2551#0#0#0
  • ​输出​​:
    • 如果地址合法,输出对应的32位整数(十进制形式),例如214754918316777216
    • 如果地址非法,输出invalid IP
地址合法性规则
  1. ​格式​​:必须由4个小节组成,以#分隔,例如A#B#C#D
  2. ​范围​​:
    • 第一节(A):1~128(闭区间)。
    • 第二节(B)、第三节(C)、第四节(D):0~255(闭区间)。
  3. ​其他非法情况​​:
    • 小节数量不是4个。
    • 某一个小节不是数字。
    • 数字超出范围。
    • 数字前导有无效字符(例如012是合法的,但+1212a是非法的)。
转换规则

将虚拟IPv4地址的4个小节分别看作一个8位二进制数,按顺序拼接成一个32位二进制数,然后转换为十进制整数。具体步骤如下:

  1. 将每一节转换为8位二进制:
    • 第一节(A):A的二进制,高位补0到8位。
    • 第二节(B):B的二进制,高位补0到8位。
    • 第三节(C):C的二进制,高位补0到8位。
    • 第四节(D):D的二进制,高位补0到8位。
  2. 拼接4个8位二进制,得到一个32位二进制数。
  3. 将32位二进制数转换为十进制整数。
示例
  1. 输入:128#0#255#255

    • 解析:
      • 第一节:128 → 10000000
      • 第二节:0 → 00000000
      • 第三节:255 → 11111111
      • 第四节:255 → 11111111
    • 拼接:10000000 00000000 11111111 11111111 → 0x8000FFFF
    • 十进制:2147549183
    • 输出:2147549183
  2. 输入:1#0#0#0

    • 解析:
      • 第一节:1 → 00000001
      • 第二节:0 → 00000000
      • 第三节:0 → 00000000
      • 第四节:0 → 00000000
    • 拼接:00000001 00000000 00000000 00000000 → 0x01000000
    • 十进制:16777216
    • 输出:16777216
  3. 输入:129#0#0#0

    • 解析:第一节是129,超出1~128范围。
    • 输出:invalid IP
  4. 输入:128#0#255

    • 解析:只有3个小节,不合法。
    • 输出:invalid IP
解题思路
  1. ​输入校验​​:
    • 检查是否由4个小节组成(用#分隔)。
    • 检查每一小节是否为纯数字(无前导符号或字母)。
    • 检查数字范围:
      • 第一节:1~128
      • 后三节:0~255
  2. ​转换​​:
    • 将每一节转换为整数。
    • 将每一节转换为8位二进制字符串。
    • 拼接4个8位二进制字符串。
    • 将32位二进制字符串转换为十进制整数。
  3. ​输出​​:
    • 合法:输出整数。
    • 非法:输出invalid IP

const readline = require('readline');

// 判断字符串是否为数字
function isNumeric(str) {
  for (let i = 0; i < str.length; i++) {
    if (!/\d/.test(str[i])) {
      return false; // 如果有非数字字符则返回false
    }
  }
  return true; // 全部为数字则返回true
}

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', function (input) {
  const ipSections = input.split('#'); // 将输入的字符串按照"#"分割成4个小节

  if (ipSections.length !== 4) { // 如果分割后的小节数量不等于4,则说明输入的IPv4地址格式不正确
    console.log("invalid IP");
    rl.close();
    return;
  }

  // 遍历每个部分进行检查
  for (const section of ipSections) {
    if (section.length === 0 || !isNumeric(section)) { // 检查是否为空或者是否每部分都是数字
      console.log("invalid IP");
      rl.close();
      return;
    }

    // 检查前导零的情况
    if (section.length > 1 && section[0] === '0') {
      console.log("invalid IP");
      rl.close();
      return;
    }
  }

  const firstSection = parseInt(ipSections[0], 10); // 将第一个小节转换为整数
  if (firstSection < 1 || firstSection > 128) { // 如果第一个小节的值不在1~128的范围内
    console.log("invalid IP");
    rl.close();
    return;
  }

  // 检查其余3个小节的范围
  for (let i = 1; i < 4; i++) {
    const sectionValue = parseInt(ipSections[i], 10); // 将当前小节转换为整数
    if (sectionValue < 0 || sectionValue > 255) { // 如果不在0~255范围内
      console.log("invalid IP");
      rl.close();
      return;
    }
  }

  // 计算最终的32位整数
  let ipValue = 0;
  //左移8位​​和​并累加​,在二进制中,乘以256(即 2^8)相当于将数字向左移动8位,空出最低的8位用于存放下一个字节​
  for (let i = 0; i < 4; i++) {
    ipValue = ipValue * 256 + parseInt(ipSections[i], 10); // 每个小节对应一个字节,计算最终的整数值
  }

  console.log(ipValue); // 输出最终的32位整数
  rl.close();
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值