暴力字符匹配算法的C语言实现

1、聊一聊

今天跟大家分享的这个曲子一般是在天气预报和英语试听中出现,不信你听一听绝对有种似曾相识感觉。

本篇文章主要是为讲解高效字符匹配算法的一则预告文,跟大家讲讲暴力字符匹配算法以及匹配算法在通信中如何使用。

2、暴力匹配算法介绍

1

聊聊字符匹配算法

bug菌所说的暴力匹配算法就是C标准库函数strstr(),如果你还没有使用过或者没有听到过这个函数,那就有点......。

字符匹配算法的应用其实是非常广泛的,小到信息的检索,大到网络安全监测,一种高效的字符匹配算法能够大大改善性能,所以目前对字符匹配算法的理论研究也是在一直进行着。

可是理论算法研究和实际应用还是有一定的脱节,往往一些高级的算法并没有得到广泛的工程应用,面对目前快节奏的功能开发形成了 : "算法的思想越简单,实际应用的效果越好"的思想。

所以bug菌从最简单的匹配算法跟大家讲起,对一些匹配性能要求不高的项目还是非常奏效的。

2

暴力字符匹配的实现原理

暴力字符匹配算法的实现原理还是非常简单的,从第一个字符开始进行匹配,如果匹配不成功,移动到下一个字节重新开始逐个匹配,其实现过程如下图所示:

看似该算法实现得理所当然,不过对于部分情况其效率相对比较低下,看看如下情况:

上图是按照暴力字符匹配算法进行的匹配过程,我们如果仔细分析一下可以发现第二步的比较是必然不会成立的,因为第一步abab都匹配成功了,移动一位肯定是匹配不成功的,所以这样就增加了算法在时间上的复杂度,有没有更优的算法解决这个问题? 答案肯定是有的,下篇文章跟大家详细介绍。

不过暴力匹配算法的好处就是理解上非常的简单,也可以说比较呆吧,往往简单的东西更加容易让大家接受,并且应用在实际的项目中,除非特别是对匹配效率比较敏感的项目。

3、暴力匹配的C代码实现

1

参考实现1

strstr()既然是标准C库函数,那么稍微大一点的软件源码都会有相应的实现,一般都写得比较精炼的,那么看看Linux源码咯,于是截图了其实现函数供大家参考:

对于linux里面的strstr实现比较清晰,获得两个字符串的长度,然后逐位比较模式串与主串的长度,如果匹配返回成功,否则把主串指针移动一位继续循环比较。

上面的代码看似比较简单,如果真的徒手写一个你还真不一定考虑得那么全面,比如下面几个细节:

  • strstr函数的形参均采用const char *的形式,这就回到了老生常谈的const的用法了<参考:一文搞定C语言const关键字>,即不允许函数内部修改指针所指向的地址数据内容,对数据起到一定的保护作用。

  • memcmp采用const void *<参考:【C进阶】同事用void把我给秀翻了!>,使得函数更加通用。

  • 内部for里面采用逗号表达式<参考:【C进阶】听说用 “ 逗号表达式 ” 仅仅为了秀技?> ,程序更加紧凑、精炼。

  • 以及size_t是什么东西,为什么使用它?

2

参考实现2

然而bug菌在翻阅一些代码中发现,还有strstr采用汇编来实现的,毕竟库函数相对比较固定,其主要是为了能够加快运算速度,下面是X86的strstr实现,供大家欣赏一下即可:

3

简化版实现

在平时的mcu开发中,bug菌不太喜欢调用库函数,就像上面的实现,一个不太复杂的程序里面进行了较多函数的嵌套,可能在性能强悍的芯片上倒问题不大,不过对于一些频繁使用该函数的中低端芯片来说性能上还是会有一定的损失的。

所谓”高端秀功能,低端秀成本”,所以来个常用的简化版本,供大家参考:

 1#include <stdio.h>23char* pChild = "123";4char* pParent = "456789123789456123" ;56char* strstr(const char*s1,const char*s2)7{8    int n;9    if(*s2)
10    {
11        while(*s1)
12        {
13            for(n=0;*(s1+n)==*(s2+n);n++)
14            {
15                if(!*(s2+n+1))
16                    return(char*)s1;
17            }
18            s1++;
19        }
20        return NULL;
21    }
22    else
23        return (char*)s1;
24}
25
26int main(int argc, char *argv[]) {
27
28    printf("  %d\n",strstr(pParent,pChild) - pParent);
29    printf("公众号:最后一个bug\n");
30    return 0;
31}

4、暴力匹配在通信中的使用

1

应用

如果仅仅只是匹配字符或者关键字等等,上面的代码可以直接拿来使用,在有些字节流的通信协议中都会存在帧头和帧尾的匹配问题,字符的匹配和帧头尾匹配思路上是一致的,所以仅仅只需要对函数进行改造以适应字节数据查找即可。

一般都会把数据接收以后放入buff中,然后通过匹配算法查找帧头,帧尾,通过定位帧头进而确定通信格式和数据完整性分析等。所以这里把字符匹配算法修改一下,获得如下代码:

 1typedef unsigned char uint8_t;2typedef unsigned int  uint16_t;34#include <stdio.h>56uint8_t Head[3] = {0x01,0x02,0x03};7uint8_t Buff[10] = {0x01,0x01,0x01,0x02,0x02,8                    0x01,0x02,0x03,0x02,0x02};9
10uint8_t* Bytestrstr(const uint8_t *s1 ,uint16_t len1,uint8_t*s2,uint16_t len2)
11{
12    uint16_t n;
13    uint16_t cnt;
14
15    if(*s2 || len2) 
16    {
17        for(cnt = 0;cnt < len1;cnt ++)
18        {
19            for(n=0;*(s1+n)==*(s2+n);n++)
20            {
21                if(n == (len2-1))
22                    return(uint8_t*)s1;
23            }
24            s1++;
25        }
26        return NULL;
27    }
28    else
29        return (char*)s1;
30}
31
32int main(int argc, char *argv[]) {
33
34    printf("  %d\n",Bytestrstr(Buff,10,Head,3) - Buff);
35    printf("公众号:最后一个bug\n");
36    return 0;
37}

    

对于以后跟大家介绍的高效字符匹配算法经过类似修改以后均可以用到字节流传递过程中来。

5、最后小结

暴力字符串匹配算法就说这么多了。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

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

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

相关文章

Python 3 学习——函数扩展and迭代器生成器装饰器

Python 学习的第九小节 写此博客 是为了激励自己&#xff0c;并且将自己的心得以及遇到的问题与人分享 一、学习笔记 1. 高阶函数 函数名可以作为函数参数输入 、可以进行赋值、还可以作为返回值。 2.作用域 在Python中&#xff0c;只有模块、类以及函数才会引入新的作用域&…

鲜茄牛肉

鲜茄牛肉 【材料】 嫩牛肉150克、番茄1个、葱2根 调味料 &#xff08;1&#xff09;酒1大匙、酱油1大匙、糖半茶匙、芡汁半大匙、色拉油1大匙 &#xff08;2&#xff09;酱油1大匙、盐1/4茶匙、糖1茶匙、芡汁1大匙 【作法】 1.牛肉切薄片&#xff0c;拌入调味料&#xf…

AfxParseURL

AfxParseURL AfxParseURL(LPCTSTR pstrURL,DWORD& dwServiceType,CString& strServer,CString& strObject,INTERNET_PORT& nPort)。 目录 1 功能 2 定义 3 返回值 4 例子 5 关于 功能 编辑 该函数解析URL字符串并返回服务的类型及组件,包含在 afxinet…

TQ210 —— LCD

TQ210 —— LCD一、LCD控制器1、S5PV210 LCD控制器要使一块LCD正常的显示文字或图像&#xff0c;不仅需要LCD驱动器&#xff0c;而且还需要相应的LCD控制器。在通常情况下&#xff0c;生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起&#xff0c;而LCD控制器则是…

P1372 又是毕业季I

题目背景 “叮铃铃铃”&#xff0c;随着高考最后一科结考铃声的敲响&#xff0c;三年青春时光顿时凝固于此刻。毕业的欣喜怎敌那离别的不舍&#xff0c;憧憬着未来仍毋忘逝去的歌。1000多个日夜的欢笑和泪水&#xff0c;全凝聚在毕业晚会上&#xff0c;相信&#xff0c;这一定是…

微信表情都戒烟了

昨天看到最新的微信表情是这样的原来的抽烟表情被替换成了这释放出一个信号&#xff0c;就是「抽烟不酷了」不过我想说&#xff0c;只戴着一个绿帽子&#xff0c;嘴巴里面什么都没有&#xff0c;好像也不酷啊。难道重点就是那个墨镜????&#xff1f;不过&#xff0c;在PC版…

这个代码应该怎么写???

这个代码应该怎么写??? Delphi / Windows SDK/APIhttp://www.delphi2007.net/DelphiDB/html/delphi_20061222151309162.html我用DELPHI和SQL SEVER做了一个系统,现在一个窗口做了一个 帮助按键,我想点它就能打开一个名为help.txt的使用帮助文档,代码要怎么写? 麻烦高…

Python 类的属性和实例属性 Python 的动态语言

#定义一下类, 含有类属性 aaa, >>> class Aa: ... aaa 10... #对类 Aa实例化出一个实例 a1>>> a1 Aa() >>> print(a1.__dict__)#查看实例并没有自己的方法和属性{}>>> a1.aaa #但是这个实例在调用属性的时候, 发现自己没有这个属性, 于…

高效KMP字符匹配算法就这么简单

1、聊一聊上一篇文章"暴力"字符匹配算法的C语言实现2、KMP算法介绍1KMP介绍KMP是一种字符匹配算法&#xff0c;为啥叫KMP呢&#xff1f;因为是由D.E.Knuth&#xff0c;J.H.Morris和V.R.Pratt大佬提出来的。那一些小伙伴会问了怎么不叫"DJV算法"呢?因为老外…

安装MyEclipse得心得

我使用的MyEclipse是MyEclipse_5.5.1GA_E3.2.2_Installer.exeEclipse是eclipse-SDK-3.2-win32Tomcat是Tomcat 6.0JDK是jdk-6u7-windows-i586-p.exe来搭建得JSP开发环境要说Java最麻烦的还是搭建环境&#xff0c;尤其对于我这种菜鸟级的人来说简直是一个小小得错误就让我停滞很久…

TQ210 —— NandFlash

TQ210 —— nandflashTQ210 开发板板载一片 1Gbyte 的 NAND FLASH——K9K8G08U0B&#xff0c;通过查询K9K8G08U0B 芯片手册可以得到如下信息&#xff1a;&#xff08;理论知识不再介绍&#xff09;K9K8G08U0B : (1G 32M) x 8bit 总大小Data Register : (2K 64) x 8bit 数据寄…

涂鸦赞助的500个开发套件,先到先得

来源 | 涂鸦跟涂鸦申请的福利&#xff0c;给喜欢开发的同学发放开发套件&#xff0c;只要是不是专门白嫖党&#xff0c;数量可以不做限制。去年疫情突发&#xff0c;封城、封小区以及人员隔离&#xff0c;让原本享受千般宠爱的主子们变成了靠吃猫砂、塑料袋度日的小可怜&#x…

Oracle 1204 RAC failover 测试 (二)

1.检查数据库状态,状态正常 [oracleracdb01 rac]$ crs_stat -t Name Type Target State Host ------------------------------------------------------------ ora.rac.db application ONLINE ONLINE racdb01 ora....s1.…

ARM中断返回地址详细分析

ARM中断返回地址详细分析 在ARM体系中&#xff0c;通常有以下3种方式控制程序的执行流程&#xff1a;1、在正常执行过程中&#xff0c;每执行一条ARM指令&#xff0c;程序计数器PC的值加4个字节&#xff1b;每执行一条Thumb指令&#xff0c;程序计数器PC加2个字节。整个过程是顺…

C++识别二维码

C识别二维码 https://blog.csdn.net/coolingcoding/article/details/25804129 https://blog.csdn.net/sw5131899/article/details/52848957 https://blog.csdn.net/weichaohnu/article/details/8275829

Linux-C 编程 / 网络 / 超迷你的 web server

一、为生活寻找固定的支撑点1. 什么是生活的支撑点&#xff1f;让自己感到些许痛苦&#xff0c;但却会带来实实在在的充实感和成就感的事情。举个栗子&#xff0c;我的支点是运动、看书、研究技术。2. 固定的支撑点很重要&#xff1a;三个固定的要素&#xff1a;时间 / 空间 / …

20165326 java第四周学习笔记

第四周学习笔记 ch5 子类和父类子类只能有一个父类使用关键字extendsyclass 子类 extends 父类系统默认的祖先类Object&#xff08;java.lang包中&#xff09;继承&#xff1a;子类继承父类的方法可以直接作为实例方法调用&#xff0c;继承的成员变量和方法的访问权限不变&…

用VSTS进行网站压力测试

VSTS提供了一个丰富、强大的工具平台&#xff0c;融合了软件开发领域的各个角色&#xff0c;涵盖软件开发生命周期的各个阶段&#xff0c;包括设计&#xff0c;开发&#xff0c;测试&#xff0c;管理&#xff0c;而这一整套构件的融会贯通&#xff0c;让它可以有效地改善软件开…

基于 DirectShow 的播放器

https://blog.csdn.net/leixiaohua1020/article/details/13019147 COM编程之 QueryInterface https://www.cnblogs.com/Braveliu/p/3435560.html

第四周选做作业

相关知识点的总结 通过命令行引入参数递归循环课上内容的补做&#xff0c;结果截图 未完成内容:递归与循环 补做教材第二章&#xff0c;第三章编程题目 参考资料 2016-2017-2 《Java 程序设计》课堂实践项目编写一个Java应用程序,输出全部的希腊字母。_百度知道[]转载于:https:…