超详细讲解字符串查找函数(保姆级教程!!!)
超详细讲解字符串查找函数(保姆级教程!!!)
- 字符串查找函数
- strstr函数
- strstr函数的使用
- strstr函数的模拟实现
- strtok函数
- strtok函数的使用
- strtok函数的模拟实现
- strpbrk函数
- strpbrk函数的使用
- strpbrk函数的模拟实现
- strcspn函数
- strcspn函数的使用
- strcspn函数的模拟实现
- strspn函数
- strspn函数的使用
- strspn函数的模拟实现
字符串查找函数
strstr函数

strstr函数是在字符串 str1 中查找第一次出现字符串 str2的位置,不包含终止符 ‘\0’。
str1 – 要被检索的 C 字符串。
str2 – 在 str1 字符串内要搜索的小字符串。
strstr函数的使用
下面是strstr函数的使用例子:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{char str[] ="This is a simple string";char * pch;pch = strstr (str,"simple");strncpy (pch,"sample",6);puts (str);return 0;
}
strstr函数的模拟实现
要在str1中查找str2并打印出来,先判断str1和str2指向的字符是否相等,此时有两种情况:
第一种情况指向的字符不相等,str1要指向下一个字符,再判断,如此循环往复,当str1指向的是 ‘\0’ 时,可以判断出str1中不存在str2,此时返回NULL;
第二种情况下指向的字符相等,那么不仅str1要向后读取字符,str2也要向后读取字符,再判断是否相等。

strstr函数的模拟实现如下:
char * strstr (const char * str1, const char * str2) {char *cp = (char *) str1;char *s1, *s2;if ( !*str2 )return((char *)str1);while (*cp){s1 = cp;s2 = (char *) str2;while ( *s1 && *s2 && !(*s1-*s2) )s1++, s2++;if (!*s2)return(cp);cp++;}return(NULL);
而实现strstr函数,除了上述的偏暴力算法的模拟实现方式之外,还可以通过KMP算法进行实现。
KMP算法:Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。
算法的核心思想是:
假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置
如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了j - next [j] 位。
具体的KMP算法思想编者会另行写一篇文章向大家大致阐述,这里就不多在赘述,有兴趣的读者可以去了解一下。
strtok函数

char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。
str – 要被分解成一组小字符串的字符串。
delim – 包含分隔符的 C 字符串。
该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。
strtok函数的使用
下面演示strtok函数的用法:
#include <string.h>
#include <stdio.h>int main () {char str[80] = "This is - www.xxxxx.com - website";const char s[2] = "-";char *tmp;tmp = strtok(str, s);while( tmp != NULL ) {printf( "%s\n", tmp );tmp = strtok(NULL, s);}return(0);
}
编译并运行上面的程序将产生以下结果:
This is
www.xxxxx.com
website
原字符串的改动是切分符原位置均更改为 ‘\0’,所以内容都还在
strtok函数具有以下的特点:
1、delim参数是个字符串,定义了用作分隔符的字符集合
2、第一个参数指定一个字符串,它包含了0个或者多个由delim字符串中一个或者多个分隔符分割的标记。
3、strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。
4、strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
并且可修改。
5、strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
中的位置。
6、strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。
7、如果字符串中不存在更多的标记,则返回 NULL 指针。
strtok函数的模拟实现
char* my_strtok(char* str, const char* sep)
{static char* s1 = NULL;static char* s2 = NULL;static int len1 = 0;static int count = 0;int len2 = 0;int i = 0;assert(sep != NULL);if (str != NULL) {s1 = str; len1 = strlen(str);len2 = strlen(sep);for (*str;*str != '\0';str++) {for (i = 0;i < len2;i++) {if (i == 0){count++;}if (*str == *(sep + i)) {*str = '\0'; s2 = str; return s1;}}}}else{s1 = s2 + 1; len2 = strlen(sep);str = s1; for (*str;*str != '\0';str++) {for (i = 0;i < len2;i++) {if (i == 0){count++;}if (*str == *(sep + i)) {*str = '\0'; s2 = str;return s1;}}}}if (count > len1){return NULL;}return s1;
}
strpbrk函数

char *strpbrk(const char *str1, const char *str2) 检索字符串 str1 中第一个匹配字符串 str2 中字符的字符,不包含空结束字符。也就是说,依次检验字符串 str1 中的字符,当被检验字符在字符串 str2 中也包含时,则停止检验,并返回该字符位置。
str1 – 要被检索的 C 字符串。
str2 – 该字符串包含了要在 str1 中进行匹配的字符列表。
strpbrk函数的使用
下面展示strpbrk函数的使用:
#include <stdio.h>
#include <string.h>int main ()
{const char str1[] = "abcde2fghi3jk4l";const char str2[] = "34";char *ret;ret = strpbrk(str1, str2);if(ret) {printf("第一个匹配的字符是: %c\n", *ret);}else {printf("未找到字符");}return(0);
}
强调的是,找的是str1中,str2的第一个匹配的内容的地址。
strpbrk函数的模拟实现
char* find_char(char const* str1, char const* str2)
{assert(str1 != NULL);assert(str2 != NULL);char* tmp = (char*)str2;while (*tmp != '\0'){char* pso = (char*)str1;while (*pso != '\0'){if (*pso != *tmp){++pso;}else{return pso;}}tmp++;}return 0;
}
strcspn函数

size_t strcspn(const char *str1, const char *str2) 检索字符串 str1 开头连续有几个字符都不含字符串 str2 中的字符。
str1 – 要被检索的字符串。
str2 – 该字符串包含了要在 str1 中进行匹配的字符列表。
strcspn函数的使用
下面演示strcspn函数的用法:
#include <stdio.h>
#include <string.h>int main ()
{int len;const char str1[] = "ABCDEF4960910";const char str2[] = "013";len = strcspn(str1, str2);printf("第一个匹配的字符是在 %d\n", len + 1);return(0);
}
编译并运行上面的程序将产生以下结果:
第一个匹配的字符是在 10
strcspn函数的模拟实现
size_t my_strcspn(const char* str1, const char* str2)
{int i = 0;char* pstr1 = (char*)str1;assert(NULL != str1);assert(NULL != str2);while (*pstr1){char* pstr2 = (char*)str2;while (*pstr2 && *pstr1 != *pstr2)++pstr2;if (*pstr1 == *pstr2)break;++pstr1;}return (pstr1 - str1);
}
strspn函数

size_t strspn(const char *str1, const char *str2) 检索字符串 str1 中第一个不在字符串 str2 中出现的字符下标。
str1 – 要被检索的字符串。
str2 – 该字符串包含了要在 str1 中进行匹配的字符列表。该函数返回 str1 中第一个不在字符串 str2 中出现的字符下标。
strspn函数的使用
下面演示 strspn函数的用法:
#include <stdio.h>
#include <string.h>int main ()
{int len;const char str1[] = "ABCDEFG019874";const char str2[] = "ABCD";len = strspn(str1, str2);printf("初始段匹配长度 %d\n", len );return(0);
}
编译并运行上面的程序将产生以下结果:
初始段匹配长度 4
strspn函数的模拟实现
size_t my_strspn(const char* str1, const char* str2)
{int i = 0;char* pstr1 = (char*)str1;assert(NULL != str1);assert(NULL != str2);while (*pstr1){char* pstr2 = (char*)str2;while (*pstr2 && *pstr1 != *pstr2)++pstr2;if (*pstr1 == *pstr2)break;++pstr1;}return (pstr1 - str1);
}
那么,今天的C语言 柔性数组的使用详解的相关内容我就讲述完啦,因为个人能力有限,文章难免会出现纰漏,届时有错误可以私信发给我以及时更正,谢谢大家!

相关文章:
超详细讲解字符串查找函数(保姆级教程!!!)
超详细讲解字符串查找函数(保姆级教程!!!)字符串查找函数strstr函数strstr函数的使用strstr函数的模拟实现strtok函数strtok函数的使用strtok函数的模拟实现strpbrk函数strpbrk函数的使用strpbrk函数的模拟实现strcspn…...
LeetCode-1138. 字母板上的路径【哈希表,字符串】
LeetCode-1138. 字母板上的路径【哈希表,字符串】题目描述:解题思路一:首先考虑坐标位置,字符是有序的从0开始,当前字符c的行为(c-a)/5,列为(c-a)%5。其次是考虑特殊情况z。若当前从‘z’开始则只能往上走;若是其他字符…...
Vue 可配置化的路由缓存(Vu2 Vue3)
Vue 可配置化的路由缓存(Vu2 & Vue3) 1 介绍 在Vue的项目当中,路由缓存是一个比较常见的功能,譬如,从列表页面进入到详情页面,返回到列表页面时,如果可以保持列表的状态,那用户…...
Linux VPU驱动
1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 2. 概述 VPU 是用来进行图像、视频数据进行硬件编、解码的硬件模块。内部集成了 Encoder、Decoder 功能部件进行图像、视频数据进行硬件编、解码&a…...
spring 笔记
一、spring概述 1.1 spring介绍 spring是一个轻量级的控制反转和面向切面的容器框架,用来解决企业项目开发的复杂度问题---解耦 轻量级:体积小,对代码没有侵入性控制反转:IOC inverse of control, 把创建对象的工作交…...
Java日志框架学习
首先,Java日志框架可以分为两类:门面型日志框架和记录型日志框架。 门面型日志框架 JCL:Java日志接口,后更名为Commons LoggingSLF4J:是一套简易Java日志门面,本身并无日志的实现 记录型日志框架 JUL&a…...
基础面试题:堆和栈的区别
面试题:堆和栈的区别(往往讲的是内存zha) 为什么说访问栈栈比访问堆快些? 目录 一、数据结构中的堆栈 1、数据结构中的堆 1)堆的定义 2)堆的效率 2、 数据结构中的栈 二、内存中的堆栈 1、内存堆的定义…...
(干货教程)在VSCode并使用chatgtp插件编写CC++语言程序
(干货教程)在VSCode并使用chatgtp插件编写CC语言程序 下载并安装VSCODE 第1步,下载VSCODE https://code.visualstudio.com/Download 第2步,安装VSCODE 安装过程较简单,这里省略。 安装好后效果如图:…...
【思维模型】概率思维的价值:找到你的人生算法,实现阶级跃迁!
把同样公平的机会放在放在很多人面前,不同的人生算法,会得到迥然不同的结果。 概率思维是什么? 【ChatGPT】概率思维是一种通过使用数学模型来思考和评估不确定性事件的方法。它通过计算不同可能性的概率来预测事件的结果,并评估风险和机会。 概率思维的价值在于它可以帮…...
SpringBoot + kotlin/java + Mybatis-Plus +Sqlite + Gradle多模块项目
前言 我自己的业务项目,先用kotlinspringboot 搭建, 发现gradle支持kts脚本,于是我就搭建试试。我就选用了最流行的Sqlite内嵌数据库,虽然H2也不错,但是Sqlite才是最流行的。orm框架我还是选择了Mybatis-Plus ,为此中…...
Docker 容器与容器云读书笔记(一)
最近都没时间看书,闲暇之余看看书,写写笔记,记录一下这难得的时光。 docker容器的出现 2013年初, 一个名字从云计算领域横空出世,并在整个IT行业激起千层浪,这就是Docker。Docker选择容器作为核心和基础&…...
软件设计(九)
软件设计(八)https://blog.csdn.net/ke1ying/article/details/128954569?spm1001.2014.3001.5501 81、模块A将学生信息,即学生姓名、学号、手机等放到一个结构体系中,传递给模块B,模块A和B之间的耦合类型为 什么耦合…...
FoveaBox原理与代码解析
paper:FoveaBox: Beyond Anchor-based Object Detectorcode:https://github.com/taokong/FoveaBox背景基于anchor的检测模型需要仔细设计anchor,常用方法之一是根据特定数据集的统计结果确定anchor的number、scale、ratio等,但这种…...
Linux内核启动(1,0.11版本)启动BIOS与加载内核
从电源到启动BIOS 从我们按下启动电源到BIOS,按下电源–>主板会向电源组发出信号–> 接受到信号后,当主板收到电源正常启动信号后,主板会启动CPU(CPU重置所有寄存器数据,并且初始化数据),比如32位系统ÿ…...
python制作贪吃蛇小游戏,畅玩无限制
前言 大家早好、午好、晚好吖 ❤ ~ 现在这年头,无论玩个什么游戏都有健康机制, 这让我们愉悦玩游戏得步伐变得承重起来, 于是无聊之下我写了个贪吃蛇小游戏,来玩个快乐 代码展示 导入模块 import random import sys import …...
MySQL-InnoDB数据页结构浅析
在MySQL-InnoDB行格式浅析中,们简单提了一下 页 的概念,它是 InnoDB 管理存储空间的基本单位,一个页的大小一般是 16KB 。 InnoDB 为了不同的目的而设计了许多种不同类型的 页: 存放表空间头部信息的页存放 Insert Buffer信息的…...
Java、JSP职工人事管理系统设计与实现
技术:Java、JSP等摘要:现在随着我们这个社会的计算机技术的快速发展,计算机在企业管理中得到普遍的应用,现在我们利用计算机在实现企业职工的管理越来越重要。当今社会是快速发展的信息社会,自动化信息的作用也变得越来…...
数据结构与算法这么难,为什么我们还要学习?
文章目录前言1. 数据结构与算法是什么?2. 为什么数据结构与算法很难?3. 如何系统学习数据结构与算法?🍑 复杂度🍑 线性表🍑 树形结构🍑 图🍑 排序🍑 字符串🍑…...
剑指 Offer 52. 两个链表的第一个公共节点
摘要 剑指 Offer 52. 两个链表的第一个公共节点 一、双指针解法 使用双指针的方法,可以将空间复杂度降至 O(1)。只有当链表 headA headB都不为空时,两个链表才可能相交。因此首先判断链表 headA和 headB是否为空,如果其中至少有一个链表为…...
可以写进简历的软件测试电商项目,不进来get一下?
前言 说实话,在找项目的过程中,我下载过(甚至付费下载过)N多个项目、联系过很多项目的作者,但是绝大部分项目,在我看来,并不适合你拿来练习,它们或多或少都存在着“问题”ÿ…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
