【C语言】strstr函数刨析-----字符串查找

news2024/11/17 5:20:54

目录

一、strstr 函数介绍

✨函数头文件: 

✨函数原型:

✨函数解读

✨功能演示

 二、函数的原理以及模拟实现

✨函数原理 

✨函数的模拟实现 

 三、strstr函数的注意事项

四、共勉 


一、strstr 函数介绍

strstr函数一个字符串中查找另一个字符串第一次出现并返回该位置的指针,如果找不到,则返回NULL。

✨函数头文件: 

#include <string.h>

✨函数原型:

const char * strstr ( const char * str1, const char * str2 );

str1被查找目标字符串

str2要查找对象字符串

 ✨函数解读

 ✨功能演示

解读完函数后,我们来用一用它,看一下str2这个子串在str1中 

int main(void)
{
	char str1[] = "abcdefabcdef";
	char str2[] = "def";

	char* substr = strstr(str1, str2);
	printf("%s\n", substr);
	return 0;
}
  • 可以看到,最后返回的结果是子串def在主串abcdefabcdef中出现的第一个位置,我们使用%s去打印的话就会从这个位置开始往后打印后面的字符串

  • 但我若是去更换一下str2的话,它就不存在于str1中了

 二、函数的原理以及模拟实现

✨函数原理 

 strstr函数的实现可以通过遍历字符串的方式来查找str2字符串的出现位置。

1,遍历str1字符串,逐个字符与str2字符串进行比较。

2,如果str1字符串的当前字符与str2字符串的第一个字符相等,则继续比较后续字符。

3,如果str1字符串中的连续字符与str2字符串完全匹配,则返回该位置的指针。

4,如果str1字符串遍历完毕仍未找到匹配,则返回NULL。 

✨函数的模拟实现 

 接下去的话我们就来模拟实现这个strstr()函数比较复杂一些,要集中注意力哦!

情况①:匹配一次就成功

  • 首先是第一种情况,那就是子串在和主串匹配的时候一次就能匹配成功了

 情况②:匹配多次才成功

  • 接下去第二种情况,就是需要匹配多次才能成功,可以看到一开始前面出现了b b b,但是我们要匹配的子串是b b c,所以在匹配到第三个b的时候就需要进行重新匹配
  • 那若是要重新匹配的话就需要让【s1】和【s2】进行重新置位的操作,【s2】的话很简单,直接回到初始的位置即可,但是对于【s1】的话其实没有必要,我们可以设置一个【p】记录子串在主串中的位置,如果在匹配的过程中失配了,只需要让【s1】回到p + 1的位置即可,因为从【p】的位置开始已经不可以匹配成功了,具体地我在下面讲述代码的时候细说

 首先给出整体代码可以先看看

const char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = str1;
	const char* s2 = str2;
	const char* p = str1;

	while (*p)
	{
		s1 = p;
		s2 = str2;
		while (s1 != '\0' && s2 != '\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return p;		//此时p的位置即为子串s2在s1中出现的第一个位置
		}
		p++;
	}
	return NULL;		//若是主串遍历完了还是没有找到子串,表明其不在主串中,返回NULL
}

 细说一下:

  • 首先我们看到开头的三个指针定义,因为在失配的时候需要指针回到字符串的起始位置,所以【str1】和【str2】的位置我们不可以去动它,那两个指针另外做移动,然后再拿一个【p】记录位置
const char* s1 = str1;
const char* s2 = str2;
const char* p = str1;
  • 在while循环内存,最主要的还是这段匹配的逻辑,若是*s1*s2中的存放的字符相同的话,就继续往后查找,但是呢它们不能一直无休止地往后查找,总有停下来的时候,那也就是当指针所指向的内容为\0时,就需要跳出循环
while (s1 != '\0' && s2 != '\0' && *s1 == *s2)
{
	s1++;
	s2++;
}
  • 若只是二者不相同跳出来了,此时p++即可,然后回到循环判断*p是否为\0,若还没有碰到主串末尾的话,就需要更新s1s2的位置,继续进行匹配的逻辑
p++;
s1 = p;
s2 = str2;
  • 若是*s2 == '\0'的话,此时就表示子串已经匹配完成了,都到达末尾了,那么这个时候我们应该返回【子串在主串中出现的第一个位置】,这也是strstr()的本质,那么这个位置在哪里呢?因为我们是哪p去记录位置的,那就可以说在主串中从指针p所指向的这个位置开始直到*s2到末尾时,即为匹配成功子串的一个位置
if (*s2 == '\0')
{
	return p;		//此时p的位置即为子串s2在s1中出现的第一个位置
}

 三、strstr函数的注意事项

在使用strstr函数时,需要注意以下几点: 

1,函数返回的指针指向的是str1字符串中匹配到的位置,因此可以通过指针的偏移量来得到具体的位置。 

#include <stdio.h>
#include <string.h>
 
int main()
{
	char str1[] = "hello world!";
	char str2[] = "world!";
	char* ret = strstr(str1, str2);
	if (ret == NULL)
		printf("找不到!\n");
	else
	    printf("%d\n", ret - str1);
 
	return 0;
}

 上述代码中,我们在字符串str1中查找字符串str2的第一次出现,并打印位置。如果找到了,则打印出位置的偏移量;如果未找到,则打印“找不到”。

 2,如果需要查找字符串的最后一次出现,可以配合使用strstr函数。

3. 函数的参数str1和str2都应该是以'\0'结尾的字符串,否则可能会导致不可预料的结果。

四、共勉 

   以下就是我对 strstr函数 的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对 C++ 的理解,请持续关注我哦!!!

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

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

相关文章

Leetcode 86. 分隔链表

题目链接&#xff1a; 86. 分隔链表 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/partition-list/description/ 题目&#xff1a; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出…

CDN技术:全球化的数字内容快速分发系统

CDN技术&#xff1a;全球化的数字内容快速分发系统 在今天的互联网世界中&#xff0c;内容分发网络&#xff08;CDN&#xff09;技术起着至关重要的作用。它通过全球分布的服务器网络&#xff0c;快速、安全地将内容送达世界各地的用户&#xff0c;极大地提升了网页加载速度和…

SpringBoot+vue开发记录(二)

说明&#xff1a;本篇文章的主要内容为SpringBoot开发中后端的创建 项目创建: 1. 新建项目&#xff1a; 如下&#xff0c;这样简单创建就行了&#xff0c;JDK什么的就先17&#xff0c;当然1.8也是可以的&#xff0c;后面可以改。 这样就创建好了&#xff1a; 2. pom.xml…

【Android12】Bugreport实现原理

Bugreport实现原理 Bugreport Bugreport介绍 Android Bugreport是一个用于记录和收集 Android设备上系统信息、日志和调试信息的工具。 系统发生某些问题时&#xff0c;可以通过bugreport把系统当前时刻点&#xff08;运行BugRepot的时刻&#xff09;的系统相关的状态和信息…

Redis中BitMap在钉钉机器人中的应用

性能分析 数据库中有1000w用户&#xff0c;每个用户签到一次&#xff0c;对应两个字段 连续签到多少次 、签到时间。 签到时间字段占用10个字节&#xff0c;连续签到多少天 占用5个字节&#xff08;假设一个用户能活100年&#xff0c;每天都签到&#xff0c;一个用户最多签到3…

【爬取研招网指定学校专业信息】

前言 本文介绍了如何使用 Python 的 requests 库和 BeautifulSoup 库来爬取研究方向信息&#xff0c;并将其保存为 CSV 文件。爬取的网站为“中国研究生招生信息网”&#xff08;https://yz.chsi.com.cn/&#xff09;。代码从指定的专业目录页面爬取研究方向的相关信息&#x…

ROM修改进阶教程------services.jar文件过小 合并odex apk合并odex 几种方法步骤解析

在上期博文中有说明去卡密等相关操作。但在安卓低版本中有些services.jar文件过小。大小不足1K,这种是无法直接反编译的。我们简单使用压缩软件打开查看。其中文件小的里面没有dex文件。这种需要我们先合并odex使其成为一个可以直接反编译的文件再来操作。操作也可以用于其他a…

Day 31 贪心算法理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

贪心算法理论基础 ​ 贪心算法的本质&#xff1a;选择每一个阶段的局部最优&#xff0c;从而达到系统的整体最优&#xff1b; ​ 贪心的套路就是没有套路&#xff0c;最好的策略就是举反例&#xff0c;因为大多数时候并不要求严格证明&#xff0c;只需要得到普遍性结论即可&a…

Linux之ebpf(1)基础使用

Linux之ebpf(1)基础使用 Author: Once Day Date: 2024年4月20日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可以参考专栏&#xff1a;Linux基础知识_Once-D…

C语言:数据结构(单链表)

目录 1. 链表的概念及结构2. 实现单链表3. 链表的分类 1. 链表的概念及结构 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表的指针链接次序实现的。 链表的结构跟火车车厢相似&#xff0c;淡季时车次的车厢会相应…

Github账号注册

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

NC398 腐烂的苹果

腐烂的苹果 一个腐烂的苹果每分钟可以向上下左右四个方向扩展&#xff0c;扩展之后&#xff0c;又会有新的腐烂的苹果&#xff0c;一直去腐蚀好的苹果&#xff0c;求多少分钟后&#xff0c;网格中全是烂苹果。 第一次做这道题的时候&#xff0c;想到这道题考察的其实是多源BFS…

MATLAB——M文件

M文件 MATLAB允许编写两种程序文件- 脚本−脚本文件是扩展名为.m的程序文件。在这些文件中&#xff0c;您编写了一系列要一起执行的命令。脚本不接受输入&#xff0c;也不返回任何输出。它们对工作区中的数据进行操作。 函数−函数文件也是扩展名为.m的程序文件。函数可以接…

运营商三要素核验接口-手机实名验证API

运营商三要素核验接口是一种API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;&#xff0c;主要用于通过互联网技术对接通信运营商的实名制数据库&#xff0c;以验证用户提供的手机号码、身份证号码、姓名这三项关键信息&#xff08;…

算法部署 | 使用TensorRT部署AlphaPose姿态估计算法

项目应用场景 面向 AlphaPose 姿态估计算法的推理加速场景&#xff0c;项目采用 TensorRT 进行 GPU 算法加速推理。 项目效果 项目细节 > 具体参见项目 README.md (1) 模型转换 python pytorch2onnx.py --cfg ./configs/coco/resnet/256x192_res50_lr1e-3_1x.yaml --chec…

【机器学习300问】74、如何理解深度学习中L2正则化技术?

深度学习过程中&#xff0c;若模型出现了过拟合问题体现为高方差。有两种解决方法&#xff1a; 增加训练样本的数量采用正则化技术 增加训练样本的数量是一种非常可靠的方法&#xff0c;但有时候你没办法获得足够多的训练数据或者获取数据的成本很高&#xff0c;这时候正则化技…

尚硅谷-JavaSE阶段考试与面试题库

一、基础题 1&#xff09;用最有效的的方法算出2称以8等于几 答案&#xff1a;2<<3 2&#xff09;两个对象a和b&#xff0c;请问ab和a.equals(b)有什么区别&#xff1f; ab&#xff1a;比较对象地址 a.equals(b)&#xff1a;如果a对象没有重写过equals方法&#xff0c…

Oracle中的 plsql语法

01-plsql 为什么要plsql 复杂的业务逻辑 可以使用 编程语言实现 sql无法实现 plsql也可以实现复杂的业务逻辑 为不直接使用编程语言 而是学习plsql plsql会比直接使用 编程语言 速度更快 基本语法&#xff1a; [declare --声明变量 变量名 变量类型 ] begin --代码逻辑 …

周鸿祎和雷军、马化腾相逢一笑泯恩仇

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 马云竟然没有到场&#xff0c;真是遗憾! 前两天工信部和互联网协会联合举办的中国互联网三十周年座谈会上。周鸿祎、雷军、马化腾相逢一笑泯恩仇。 第一条视频&#xff1a; 周鸿祎和马化腾握手言欢&#xff0c…

STL Array、ForwardList源码剖析

STL Array、ForwardList源码剖析 参考文章: https://blog.csdn.net/weixin_45389639/article/details/121618243 array 源代码 template<typename _Tp,std::size_t _Nm> struct array {typedef _Tp value_type;typedef _Tp* pointer;typedef value_type* iterator;// Su…