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

每日一题——验证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规则即可,还有字符串处理函数。


http://www.kler.cn/a/557873.html

相关文章:

  • 使用pyinstaller对gradio和chromadb进行打包
  • AI大模型-提示工程学习笔记13—自动提示工程师 (Automatic Prompt Engineer)
  • 数据结构、算法和STL简介 【复习笔记】
  • C++/JavaScript ⭐算法OJ⭐下一个排列
  • SAP任命Simon Davies为亚太区总裁,领导重组后的亚太地区业务
  • 第15届 蓝桥杯 C++编程青少组中/高级选拔赛 202401 真题答案及解析
  • 后渗透——Docker容器逃逸
  • 数据结构-图-找出星型图的中心节点
  • 深度学习驱动下的字符识别:挑战与创新
  • 将 Vue 项目打包后部署到 Spring Boot 项目中的全面指南
  • C# 从基础神经元到实现在0~9数字识别
  • 蓝耘智算平台携手 DeepSeek,开启 AI 超算新纪元
  • tauri2实现监听记住窗口大小变化,重启回复之前的窗口大小
  • Git 工作流程
  • 广东双9研0,目标腾讯,读研三年如何规划学习?
  • java 环境 redis信创后整合jedis
  • 视频大小怎么计算?视频码率是什么,构成视频清晰度的核心要素!
  • Pytorch实现之结合SE注意力和多种损失的特征金字塔架构GAN的图像去模糊方法
  • js如何直接下载文件流
  • #渗透测试#批量漏洞挖掘#Progress Software Flowmon命令执行漏洞(CVE-2024-2389)