【偏门技巧】C语言编程实现对IPV4地址的合法性判断(使用正则表达式)

news2024/11/22 1:07:47

C语言编程实现对IPV4地址的合法性判断(使用正则表达式)

有了解过我的朋友,可能有点印象,我在N年前的博客中,就写了这个主题,当时确实是工作中遇到了这个问题。本想着等工作搞完之后,就把这个问题的解决代码补上,结果一鸽,就是好几年,真是惭愧。现在把这部分代码公开,欢迎大家来下载测试。

文章目录

  • 1 写在前面
  • 2 什么是正则表达式
  • 3 需求分析
  • 4 C语言版本(正则表达式)
  • 5 完整测试用例

1 写在前面

之前我写过一篇博文,主要介绍如何使用C语言编程实现对IPV4地址的合法性进行判断,不过那次我使用的原生的C语言函数来实现的,本篇博文将给大家介绍一下,如何在C语言编程的环境下,使用正则表达式完成这个功能需求。

2 什么是正则表达式

正则表达式是一种用于匹配文本模式的工具,它可以通过一些特定的字符和语法规则来描述一个文本模式,并在文本中查找符合该模式的字符串。正则表达式可以用于文本搜索、替换、验证等多种应用场景,是程序员和文本处理工作者必备的工具之一。

正则表达式,在一些高级编程语言中,都有成熟的库接口来调用,而在C语言中,却鲜有这样的例子。但并不是说它不能用,其实它也是可以用的。

在C语言中使用正则表达式时,有一些注意事项需要注意:

  1. 首先需要包含regex.h头文件。
  2. 在使用正则表达式之前,需要使用regcomp()函数将正则表达式编译成一个模式。
  3. 在使用regexec()函数执行正则表达式时,可以使用REG_EXTENDED选项来启用扩展正则表达式,或使用REG_ICASE选项来忽略大小写。
  4. 在使用regexec()函数时,如果返回值为0,表示匹配成功;如果返回值为REG_NOMATCH,表示没有匹配成功;如果返回值为其他值,表示发生了错误。
  5. 在使用regerror()函数获取错误信息时,需要提供一个缓冲区和缓冲区大小。
  6. 在使用完正则表达式后,需要使用regfree()函数释放编译后的模式。
  7. 正则表达式中的特殊字符需要进行转义,例如.需要写成\.,否则它将匹配任何字符。
  8. 正则表达式中的括号可以用于分组,例如([0-9]{1,3}\.){3}[0-9]{1,3}可以匹配一个IP地址。
  9. 在使用正则表达式时,需要注意性能问题,因为正则表达式匹配可能会消耗大量的CPU资源。可以考虑使用更简单的字符串匹配算法,例如strstr()函数。

更多关于正则表达式的介绍,可以参考:正则表达式语言 - 快速参考 | Microsoft Learn

3 需求分析

其实,本专题的需求很简单,就是输入一段字符串,判断它是不是合法的IPv4地址。仅仅从功能上看,似乎很简单,但是真正要做到很完美,也是需要下点功夫的。不信,你看看下文的拆解。

IPV4 的图像结果

4 C语言版本(正则表达式)

我们先上一个简单版本,直接看代码:

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

#include <regex.h>

static int is_valid_ipv4_regex(const char *ip_address)
{
    regex_t regex;
    int reti;

    // Compile regular expression
    reti = regcomp(&regex, "^([0-9]{1,3}\\.){3}[0-9]{1,3}$", REG_EXTENDED);
    if (reti) {
        fprintf(stderr, "Could not compile regex\n");
        reti = 0;
    }

    // Execute regular expression
    printf("%s\n", ip_address);
    reti = regexec(&regex, ip_address, 0, NULL, 0);
    if (!reti) {
        printf("Valid IP address %d\n", reti);
        reti = 1;
    } else if (reti == REG_NOMATCH) {
        printf("Invalid IP address xxx %d\n", reti);
        reti = 0;
    } else {
        char error_message[100];
        regerror(reti, &regex, error_message, sizeof(error_message));
        fprintf(stderr, "Regex match failed: %s\n", error_message);
        reti = 0;
    }

exit_entry:

    // Free compiled regular expression
    regfree(&regex);

    return reti;
}


int is_valid_ipv4(const char *ip_address) 
{
    int num, dots = 0;
    char *ptr;

    if (ip_address == NULL) {
        return 0;
    }

    ptr = strtok((char *)ip_address, ".");
    if (ptr == NULL) {
        return 0;
    }

    while (ptr) {
        if (!isdigit(*ptr)) {
            return 0;
        }

        if (*ptr == '0') { //check start '0'
            return 0;
        }

        num = atoi(ptr);
        if (num < 0 || num > 255) {
            return 0;
        }

        ptr = strtok(NULL, ".");
        if (ptr != NULL) {
            dots++;
        }
    }

    if (dots != 3) {
        return 0;
    }

    if (atoi(ip_address) >= 1 && atoi(ip_address) <= 126) {
        printf("This is a Class A IP address.\n");
        return 1;
    } else if (atoi(ip_address) >= 128 && atoi(ip_address) <= 191) {
        printf("This is a Class B IP address.\n");
        return 1;
    } else if (atoi(ip_address) >= 192 && atoi(ip_address) <= 223) {
        printf("This is a Class C IP address.\n");
        return 1;
    } else {
        printf("This is not a Class A, B, or C IP address.\n");
        return 0;
    }

    return 1;
}

int check_is_valid_ipv4(const char *ip)
{
    int ret = 0;
    
    //ret = is_valid_ipv4(ip); 
    ret = is_valid_ipv4_regex(ip); 

    return ret; 
}

int main(int argc, const char *argv[])
{
    const char *ip = argv[1];

    printf("check %s\n", ip);
    printf("ret %d\n", check_is_valid_ipv4(ip));
}

编译运行一下,输入一个常见的ipv4地址是没有问题,比如 “192.168.0.1”;同时,非法的字符输入也是会报错的。

recan@ubuntu:~$ 
recan@ubuntu:~$ 
recan@ubuntu:~$ ./test 192.168.1.3
check 192.168.1.3
192.168.1.3
Valid IP address 0
ret 1
recan@ubuntu:~$ ./test 192.168.1.t
check 192.168.1.t
192.168.1.t
Invalid IP address xxx 1
ret 0
recan@ubuntu:~$ 
recan@ubuntu:~$ ./test 192.168.1.oo
check 192.168.1.oo
192.168.1.oo
Invalid IP address xxx 1
ret 0
recan@ubuntu:~$ 
recan@ubuntu:~$ ./test 192.168.01.8
check 192.168.01.8
192.168.01.8
Valid IP address 0
ret 1
recan@ubuntu:~$ 
recan@ubuntu:~$

但是细心的朋友可能互发现,当IP地址某一段带前导0时,貌似也会判断为正确的IP地址,而实际上我们一般不会这样写。

那么如何才能规避掉这种情况呢?

有没有可能通过正则表达式来完成呢?

这个问题留给读者自行去探索,是个非常有趣的正则表达式学习。

只要完成了这个功能,相信一定能够让你对正则表达式掌握得更加深入。

5 完整测试用例

本小节给大家补充一下各种测试用例,希望对大家测试代码有帮助:

合法的测试输入
192.168.0.1
10.0.0.1
172.16.0.1
255.255.255.255

非法的测试输入
256.0.0.1
192.168.0.0.1
192.168.0
192.168.0.1.2

非法的测试输入
256.0.0.1
192.168.0.0.1
192.168.0
192.168.0.1.2
300.300.300.300
1.2.3
1.2.3.4.5
1.2.3.4.
.1.2.3.4
1..2.3.4

测试用例是不断丰富的,欢迎大家来补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/560575.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++小知识点(for,nullptr)

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…

Ubuntu用户与用户组相关操作

目录 一、用户与用户组信息查看 二、用户管理 1、user1 2、user2 3、设置密码与删除用户 三、用户组管理 四、用户的切换 一、用户与用户组信息查看 查看用户&#xff0c;首先调出终端窗口&#xff0c;&#xff08;“sudo cat /etc/passwd”&#xff09;&#xff0c;输…

Day 50 小结

50.1 比较分析各种查找算法 顺序查找&#xff1a;时间复杂度&#xff1a;O(n)&#xff1b;可用于有序或无序数据&#xff1b;按顺序查找元素。 折半查找&#xff1a;时间复杂度&#xff1a;O(logn)&#xff1b;只能用于有序数据&#xff1b;从中间元素开始查找&#xff0c;每…

Linux 内核启动流程与入口函数分析

从启动引导程序 bootloader&#xff08;uboot&#xff09;跳转到 Linux 内核后&#xff0c;Linux 内核开始启动&#xff0c;今天我们分析一下 Linux 内核启动入口。 跳转过去初始化肯定是在汇编文件中&#xff0c;根据架构可以选择不同的平台&#xff0c;这里看一下链接汇编文…

STM32 Simulink 自动代码生成电机控制——记录一次电机初始位置检测及NS极的判断实验

目录 前言 基本原理 仿真实现 代码生成及开发板验证 前言 之前做了脉振高频注入的仿真到代码生成开发板运行的实验&#xff0c;电机可以通过高频注入计算出角度&#xff0c;但是在初始位置检测的时候&#xff0c;尝试了不少方法但是效果一般&#xff0c;很容易反转&#xff…

服务器模型 setsockopt 网络超时检测 广播组播和unix域套接字 5.23

四.服务器模型 1.循环服务器 TCP服务器 TCP服务器端运行后等待客户端的连接请求。 TCP服务器接受一个客户端的连接后开始处理&#xff0c;完成了客户的所有请求后断开连接。 TCP循环服务器一次只能处理一个客户端的请求。 只有在当前客户的所有请求都完成后&#xff0c;服务…

Lucene(6):分词器

1 分词理解 在对Document中的内容进行索引之前&#xff0c;需要使用分词器进行分词 &#xff0c;分词的目的是为了搜索。分词的主要过程就是先分词后过滤。 分词&#xff1a;采集到的数据会存储到document对象的Field域中&#xff0c;分词就是将Document中Field的value值切分…

netty学习第一课

技术主题 Netty是一个基于Java NIO&#xff08;非阻塞 I/O&#xff09;框架的网络编程框架。它提供了一系列的高级网络编程API&#xff0c;使得开发者可以非常容易地实现高性能、高可靠性的网络应用。Netty具有非常好的可扩展性和灵活性&#xff0c;能够很好地支持多种协议和数…

Fiddler抓包工具之fiddler的介绍及安装

Fiddler简介 Fiddler是比较好用的web代理调试工具之一&#xff0c;它能记录并检查所有客户端与服务端的HTTP/HTTPS请求&#xff0c;能够设置断点&#xff0c;篡改及伪造Request/Response的数据&#xff0c;修改hosts&#xff0c;限制网速&#xff0c;http请求性能统计&#xff…

从零实现一个数据库(DataBase) Go语言实现版 7.空闲列表: 重用页

英文源地址 由于我们的B树时不可变的, 每次对kv存储的更新都会在路径上创建新节点, 而不是更新当前节点, 从而使一些节点无法从最新版本访问到.我们需要从旧版本中重用这些不可访问的节点, 否则, 数据库文件将无限增长. 设计空闲列表 为了重用这些页, 我们将添加一个持久化存…

python处理字符串、文本实例及注释

1、多个界定符切割字符串 代码 line = asdf fjdk; afed, fjek,asdf, foo import re re.split(r[;,\s]\s*, line) 结果 在上面的例子中,分隔符可以是逗号,分号或者是空格,并且后面紧跟着任意个的空格。只要这个模式被找到,那么匹配的分隔符两边的实体都会被当成是结果中…

面了个20k的自动化测试,从腾讯出来的果然都有两把刷子···

现在找个会自动化测试的人真是难呀&#xff0c;10个里面有8个写了会自动化&#xff0c;但一问就是三不知 公司前段时间缺人&#xff0c;也面了不少测试&#xff0c;前面一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在15-20k&#xff0c;面试的…

技巧:如何查看github的热门趋势和star排行

目录 1. 查看github的热门趋势2. 查看github的star排行3. 如何查看项目star增长曲线 1. 查看github的热门趋势 手动找到入口&#xff0c;打开github&#xff0c;登录后&#xff0c;找到Explore并点击进入&#xff0c;找到Trending切换&#xff0c;列出的就是github当天所有语言…

目标检测常用模型之R-CNN、Fast R-CNN、Faster R-CNN

文章目录 一、模型分类1. 一阶段目标检测2. 二阶段目标检测 二、常见模型1. R-CNN2. Fast R-CNN3. Faster R-CNN 一、模型分类 2012年卷积神经网络(Convolutional Neural Networks, CNNs)的兴起将目标检测领域推向了新的台阶。基于CNNs的目标检测算法主要有两条技术发展路线&am…

国外顶尖高校、企业分享人工智能自学课程英文原课程分享

人工智能无疑已经是当下最火热的方向&#xff0c;在很多领域已经融入我们生活&#xff0c;ChatGPT,Midjourney只是其中一个细分热点。目前这个领域&#xff0c;虽说国内也有不少课程&#xff0c;但是大部分源头还得从英文资料中找。如何学到最新最强得人工智能技能&#xff0c;…

Mongodb——快速入门,2个小时足够了

目录 1、Mongodb概述 1.1、为何使用Mongodb&#xff1f; 1.2、业务应用场景 1.3、Mongodb和MySQL的区别 2、Mongodb安装 2.1、Windows系统中安装启动 3、Mongodb的操作 3.1、数据库操作 3.2、集合操作 3.2.1、集合显式创建 3.2.2、集合的隐式创建 3.2.3集合的删除 …

k8s进阶3——资源配额、资源限制

文章目录 一、基本了解1.1 资源计算1.2 调度机制1.3 服务质量等级 二、资源配额 ResourceQuota2.1 支持的限制资源2.2 配额作用域2.3 资源配额选型2.3.1 计算资源配额2.3.2 存储资源配额2.3.3 对象数量配额 三、资源限制 LimitRange3.1 限制资源大小值3.2 设置限制默认值3.3 限…

buu [NPUCTF2020]共 模 攻 击 1

题目描述: task: hint: 题目分析&#xff1a; 先看hint(提示)这一部分&#xff0c;标题已经提示了是共模攻击&#xff0c;看到有e1,e2,c1,c2,n也可以想到是共模攻击&#xff0c;之后得到c&#xff0c;继续往下做 此时有点不知如何下手&#xff0c;e 256 并且 gcd(e // 4,p…

接口测试工具Postman接口测试图文教程(超详细)

目录 一、前言 二、Postman安装和使用 三、请求方式 四、资金记录接口实例演示 一、前言 在前后端分离开发时&#xff0c;后端工作人员完成系统接口开发后&#xff0c;需要与前端人员对接&#xff0c;测试调试接口&#xff0c;验证接口的正确性可用性。而这要求前端开发进度…

games103——作业4

实验四主要使用 Shallow Wave 模拟流体 完整项目已上传至github。 文章目录 Height Feild(高度场)更新高度场更新速度场 Shallow Wave EquationDiscretization(离散化)一阶导数二阶导数 Discretized Shallow Wave EquationSolution 1Solution 2Pressure(压强)Viscosity(粘滞) 算…