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

每日一题——验证IP地址

验证IP地址

    • 题目描述
      • IPv4 地址规则:
      • IPv6 地址规则:
    • 示例
      • 示例 1
      • 示例 2
      • 示例 3
    • 解题思路
      • 1. IPv4 地址验证
      • 2. IPv6 地址验证
    • 代码实现
    • 代码解析
      • 1. `isValidIPv4` 函数
      • 2. `isValidIPv6` 函数
      • 3. `solve` 函数
      • 4.token = strtok(NULL, ".");
    • 复杂度分析
    • 总结

题目描述

编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址。

IPv4 地址规则:

  • 由 4 个十进制数组成,范围为 0 - 255。
  • . 分割。
  • 数字不能以 0 开头(除非是 0 本身)。

IPv6 地址规则:

  • 由 8 组 16 进制数组成,每组表示 16 比特。
  • : 分割。
  • 允许前导零,字母可以是大写或小写。
  • 不允许空组(如 ::)。
  • 不允许多余的 0(如 02001)。

数据范围
字符串长度满足 (5 \leq n \leq 50)
进阶要求

  • 空间复杂度 (O(n))
  • 时间复杂度 (O(n))

示例

示例 1

输入
"172.16.254.1"
输出
"IPv4"
说明
这是一个有效的 IPv4 地址。

示例 2

输入
"2001:0db8:85a3:0:0:8A2E:0370:7334"
输出
"IPv6"
说明
这是一个有效的 IPv6 地址。

示例 3

输入
"256.256.256.256"
输出
"Neither"
说明
这个地址既不是 IPv4 也不是 IPv6 地址。


解题思路

1. IPv4 地址验证

  • 使用 strtok. 分割字符串。
  • 检查分割后的段数是否为 4。
  • 检查每段是否为数字,且范围在 0 - 255 之间。
  • 检查是否有前导零(除非是 0 本身)。

2. IPv6 地址验证

  • 使用 strtok: 分割字符串。
  • 检查分割后的段数是否为 8。
  • 检查每段是否为有效的 16 进制数(0-9, a-f, A-F)。
  • 检查每段长度是否在 1 - 4 之间。

代码实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

// 判断是否是有效的 IPv4 地址
int isValidIPv4(char* IP) {
    int count = 0; // 段数计数器
    int len = strlen(IP); // 字符串长度
    char* token = strtok(IP, "."); // 按 '.' 分割字符串
	if (len == 0 || IP[len - 1] == ':') return 0; // 字符串为空或以冒号结尾,无效
    while (token) {
        count++; // 段数加 1
        if (count > 4 ) return 0; // 段数超过 4 无效
        int token_len = strlen(token); // 当前段的长度
        if (token_len == 0 || token_len > 3) return 0; // 段长度为 0 或超过 3,无效

        int num = 0; // 当前段的数值
        for (int i = 0; i < token_len; i++) {
            if (!isdigit(token[i])) return 0; // 字符不是数字,无效
            num = num * 10 + (token[i] - '0'); // 计算数值
        }

        if (num < 0 || num > 255) return 0; // 数值不在 0 - 255 范围内,无效
        if (token_len > 1 && token[0] == '0') return 0; // 有前导零,无效

        token = strtok(NULL, "."); // 获取下一个段
    }

    return count == 4; // 段数恰好为 4,有效
}

// 判断是否是有效的 IPv6 地址
int isValidIPv6(char* IP) {
    int len = strlen(IP); // 字符串长度
    if (len == 0 || IP[len - 1] == ':') return 0; // 字符串为空或以冒号结尾,无效

    int count = 0; // 段数计数器
    char* token = strtok(IP, ":"); // 按 ':' 分割字符串

    while (token) {
        count++; // 段数加 1
        if (count > 8) return 0; // 段数超过 8,无效
        int part_len = strlen(token); // 当前段的长度
        if (part_len == 0 || part_len > 4) return 0; // 段长度为 0 或超过 4,无效

        for (int i = 0; i < part_len; i++) {
            if (!isxdigit(token[i])) return 0; // 字符不是 16 进制数字,无效
        }

        token = strtok(NULL, ":"); // 获取下一个段
    }

    return count == 8; // 段数恰好为 8,有效
}

// 主函数,验证 IP 地址类型
char* solve(char* IP) {
    char* ipCopy = strdup(IP); // 复制 IP 字符串
    if (isValidIPv4(ipCopy)) {
        free(ipCopy); // 释放复制的字符串
        return "IPv4"; // 返回 "IPv4"
    }
    free(ipCopy); // 释放复制的字符串

    ipCopy = strdup(IP); // 再次复制 IP 字符串
    if (isValidIPv6(ipCopy)) {
        free(ipCopy); // 释放复制的字符串
        return "IPv6"; // 返回 "IPv6"
    }
    free(ipCopy); // 释放复制的字符串
    return "Neither"; // 返回 "Neither"
}

代码解析

1. isValidIPv4 函数

  • 使用 strtok. 分割字符串。
  • 检查每段是否为数字,且范围在 0 - 255 之间。
  • 检查是否有前导零。

2. isValidIPv6 函数

  • 使用 strtok: 分割字符串。
  • 检查每段是否为有效的 16 进制数。
  • 检查每段长度是否在 1 - 4 之间。

3. solve 函数

  • 复制 IP 字符串,避免修改原字符串。
  • 依次调用 isValidIPv4isValidIPv6 进行验证。
  • 返回验证结果。

4.token = strtok(NULL, “.”);

  • 第一次调用:
    第一次调用时,str 是要分割的原始字符串。strtok 会找到第一个分隔符,并将字符串从该位置分割开,返回第一个子字符串的指针。分隔符位置会被替换为 \0(字符串结束符),从而将原字符串分割成两部分。
  • 后续调用:
    后续调用时,str 参数必须传入 NULL。strtok 会从上次分割的位置继续处理,返回下一个子字符串。这个过程会一直持续,直到没有更多的子字符串为止(此时返回 NULL)。

复杂度分析

  • 时间复杂度:(O(n)),其中 (n) 是字符串长度。
  • 空间复杂度:(O(n)),用于存储复制的字符串。

总结

方法时间复杂度空间复杂度核心思想
分割字符串(O(n))(O(n))按规则分割并验证每段是否合法

这题整体难度看似难度挺大,实际上只要记住一些IP规则即可,还有字符串处理函数。

相关文章:

  • Docker教程(喂饭级!)
  • 数字化电子(不动产经营租赁服务)发票版式文件说明
  • 孜然单授权系统V2.0PHP授权系统
  • List 接口中的 sort 和 forEach 方法
  • Linux-GlusterFS进阶分布式卷
  • python 虚拟机的使用方式
  • 实验-安装Proteus
  • 大模型监督微调(SFT)技术解析
  • Open-WebUI前后端分离部署并基于DeepSeek实现智能问答
  • 虚拟机从零实现机器人控制
  • 安全面试2
  • 被裁20240927 --- WSL-Ubuntu20.04安装cuda、cuDNN、tensorRT
  • PHP post 数据丢失问题
  • .NET MVC实现电影票管理
  • 【NLP 31、预训练模型的发展过程】
  • 游戏引擎学习第118天
  • java开发——为什么要使用动态代理?
  • 0222-leetcode-1768.交替合并字符串、389找不同、
  • 异步联邦学习的动态隐私保护框架:重构边缘智能的数据安全边界
  • 采用sidecar模式,将127.0.0.1的请求打到目标机器
  • 图忆|红场阅兵:俄罗斯30年来的卫国战争胜利日阅兵式
  • 甘肃省政府原副省长赵金云被决定逮捕
  • 李公明︱一周书记:浪漫主义为什么……仍然重要?
  • 经济日报:降准降息,提前还房贷划算吗?
  • 视频丨习近平主席出席俄方在机场举行的迎宾仪式
  • 又一日军“慰安妇”制度受害者去世,大陆在世幸存者仅7人