首页 > 其他分享 >字符串函数剖析(3)---strstr函数

字符串函数剖析(3)---strstr函数

时间:2023-08-16 14:34:16浏览次数:39  
标签:p2 char p1 strstr 函数 s2 s1 --- cur

1.strstr函数的巧妙 -- 查找子字符串

1.1模拟实现strstr函数

strstr函数:在一个字符串中查找子串 学习新函数时,先去c库查找该函数的相关资料,更加助于你的学习const char * strstr ( const char * str1, const char * str2 );先看函数的声明, 参数是两个地址,不可更改。 先看看strstr函数的用法: 假如有一个字符串p1 = "abcdef" ,另一个字符串 p2 ="cde",在p1中查找p2,肉眼可见,p1中确实存在p2,用代码来展示一下:int main() { char p1[] = "abcdef" char p2[] = "cde"; char *ret = strstr(p1, p2); if (ret == NULL) { printf("%s\n", "找不到"); } else { printf("%s\n", ret); } } 可以看到,打印出了cdef,来看一下库函数的解释: 它的意思是,如果字符串1中不存在字符串2,则返回 NULL,否则,返回字符串1中出现字符串2的首次出现的地址。在上面 "abcdef" 和 "cde"的例子中,返回值则为c的地址,打印出来的话,就会顺着c的地址往下打印。那假如 是这样的例子呢? p1 = "abcdebcde" , p2 = "cde", 很明显,由库函数的返回值可知,返回的是第一次出现这个串时的地址。下面来模拟实现my_strstr函数:

在模拟实现该函数之前,我们先看一个例子,看懂这个例子,你才能看懂模拟实现的过程。假设有一字符串:p1 = "abbbcde" , p2 = "bbc",则在 p1 中查找 p2,很明显,肉眼可以知道,的确存在。 当我们去写代码时:,先看下图: ,p1 所指向的位置!= p2,所以 p1 后移一位,移动到b,此时 p1 == p2,继续后移,直到p2 指向c,p1 指向第三个b时, 此时p1 != p2,则需要将p2回溯到最开始的位置,p1也从最开始的位置的后一位开始查找,如下图: 但遗憾的是,没人记住p1 和 p2的最开始的位置,p1 和p2 一旦移动了,就不好找回原来的位置了,所以定义两个临时变量指向 p1和p2的位置, 此时我们只需要移动s1和s2即可,p1和p2保持不变,回到刚刚上面的那句加粗的话: 将p2回溯到最开始的位置,p1也从最开始的位置的后一位开始查找,这个任务就交给s1和s2来做就行,我们继续往下走:此时s1与s2所指向的第一个和第二个位置都匹配了,但是当s2指向c,s1指向第三个b时,不相同,则 s2 又回溯到p2 的位置,s1回溯到p1的 后两位,这里又出现了一个问题, p1一动不动在a这个位置,怎么知道p1的后两位是哪一个字母呢?,这又需要引入另一个变量 :cur 当我们的s1每次回溯时,cur都会往下走一位,说明没有匹配到子串。 这是p1 在每次移动时的过程: 这是p2在每次移动时的过程当每一次匹配不成功时,cur会跳转到下一位,继续匹配 看到这里,如果你明白了,那就大功告成了。char* my_strstr(const char* p1, const char* p2) { assert(p1 && p2); char* s1 = NULL; char* s2 = NULL; char* cur = (char*)p1; NUL和Null都是 '\0' if (*p2 == '\0') { return (char*)p1; } while (*cur) { abbbcdef bbc s1 = cur; s2 = (char*)p2; while (s1 && s2 && (*s1 == *s2)) { s1++; s2++; } if (*s2 == '\0') { return cur; //找到了 } if (*s1 == '\0') { return NULL;//找不到 } 相当于找完了p1串都找不到,跳出cur的循环,这里如果多写一层,就画蛇添足了 cur++; } return NULL; 找完了p1都找不到 }重点部分再次详细介绍。 结果如上: 总结:重点是理解 ”abbbcdef“ 和”bbc“这个例子就大功告成了

标签:p2,char,p1,strstr,函数,s2,s1,---,cur
From: https://blog.51cto.com/u_15818575/7107752

相关文章

  • 【230816-8】▲ABC中,AB=4,BC=2,∠A=α=∠B/2,求:AC=?
    ......
  • 【230816-7】已知:2^x=3,8^y=72 求:8^5x-6y+7=?
    ......
  • gitlab-runner register
    [root@g~]#gitlab-runnerregisterRuntimeplatformarch=amd64os=linuxpid=23614revision=ac8e767aversion=12.6.0Runninginsystem-mode.P......
  • teamcenter awc 开发-柱状图、饼状图修改颜色
    1、在对应的chartProviders下面添加"chartColorOverrideClass":"hf_aw-charts-chartColor"2、在src下创建一个scss文件@import'mixins/mixins';.hf_aw-charts-chartColor1{   background-color:#426ab3;}.hf_aw-charts-chartColor2{   backgroun......
  • 为什么在java中没有虚函数的关键字?
    因为java默认函数是虚函数,都可以被继承和重写。不想被重写需要加上final关键字。参考:C++中普通成员函数加上virtual关键字就成为虚函数。Java中其实没有虚函数的概念,它的普通函数就相当于C++的虚函数,动态绑定是Java的默认行为。如果Java中不希望某个函数具有虚函数特......
  • 无涯教程-Perl - sleep函数
    描述此函数将脚本暂停EXPR秒,如果未指定EXPR,则暂停脚本。返回实际睡眠的秒数。可以被信号处理程序打断,但是您应该避免使用带Alert的睡眠,因为许多系统将Alert用于睡眠实现。语法以下是此函数的简单语法-sleepEXPRsleep返回值此函数返回整数,实际睡眠的秒数例以下......
  • 知识图谱(Knowledge Graph)- Neo4j 5.10.0 Desktop & GraphXR 连接自建数据库
    #输入查看数据库连接neo4j$:serverstatus添加远程连接,输入连接地址GraphApps选择GraphXR打开显示......
  • 无涯教程-Perl - sin函数
    描述此函数返回EXPR的正弦值;如果未指定,则返回$_。此函数始终返回浮点数。语法以下是此函数的简单语法-sinEXPRsin返回值此函数返回EXPR的浮点正弦值例以下是显示其基本用法的示例代码-#!/usr/bin/perl$temp=sin(4);print"sinvalueof4is$temp";执行上......
  • 服务器数据恢复-HP EVA存储原理&常见故障&数据恢复流程
    EVA存储原理:EVA系列存储是以虚拟化存储为实现目的的中高端存储设备,内部的结构组成完全不同于其他的存储设备,RAID在EVA内部称之为VRAID。EVA会在每个物理磁盘(PV)的0扇区写入签名,签名后PV会被分配到不同的DISKGROUP。在DISKGROUP中每个PV会按一定大小划分为若干存储单元(PP),PP的大小......
  • 函数提高
    1.函数默认参数如果我们自己传入数据,就使用自己的数据,如果没有,就使用默认值。语法:返回值类型函数名(形参=默认值){}注意事项:1.如果某个位置已经有了默认参数,那么从这个位置往后,从左到右都必须有默认值2.如果函数的声明(原型)有默认参数,那函数的实现就不能有默认参数。声明和实现只......