字符串函数的模拟实现(strlen,strcpy,strcat,strcmp,strstr)(图文并茂,清晰易懂)

目录

  • 1. strlen函数
  • 2. strcpy函数
  • 3. strcat函数
  • 4. strcmp函数
  • 5. strstr函数

个人专栏

《零基础学C语言》

1. strlen函数

strlen函数(Get string length)的功能是求字符串长度

使用注意事项

  1. 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
  2. 参数指向的字符串必须要以 ‘\0’ 结束。
  3. 注意函数的返回值为size_t,是无符号的(易错

在这里主要讲解三种方法模拟实现

  • 方法一
  • 计数器
size_t my_strlen1(const char* str)
{assert(str);int count = 0;while (*str++){count++;}return count;
}
  • 方法二
  • 指针-指针
  • 得到的是中间元素的个数

这里我们要记录下字符串的初始位置,等str移动到 ‘\0’ 后,相减得结果

size_t my_strlen2(const char* str)
{assert(str);char* start = str;while (*str){str++;}return str - start;
}
  • 方法三
  • 递归

递归主要考虑返回条件子问题

  1. 返回条件:如果str指向 ‘\0’ ,则返回0
  2. 子问题:转化为求my_strlen(str+1) (除去本身字符的字符串)+ 1(本身字符)
size_t my_strlen3(const char* str)
{assert(str);if (*str == '\0'){return 0;}return my_strlen3(str + 1) + 1;
}

运行结果:

void TestMyStrlen()
{char arr[] = "abcdef";size_t len = my_strlen3(arr);printf("%zd\n", len);
}

2. strcpy函数

strcpy函数(Copy string)的功能是字符串拷贝

  • 将源字符串拷贝到指定空间

使用注意事项

  1. 源字符串必须以 ‘\0’ 结束。
  2. 会将源字符串中的 ‘\0’ 拷贝到目标空间。
  3. 目标空间必须足够大,以确保能存放源字符串。
  4. 目标空间必须可修改。
  5. 返回值是目标空间的地址

下面代码最巧妙的地方,在于把字符串的拷贝和 ‘\0’ 的拷贝融合在一起。循环中,先赋值,再判断,最后++。这样就算遇到 ‘\0’ ,也会先拷贝,再判断停止。

char* my_strcpy(char* dst, const char* src)
{assert(dst && src);char* ret = dst;while (*dst++ = *src++){;}return ret;
}

运行结果:

3. strcat函数

strcat函数(Concatenate strings)的功能是字符串追加

  • 将一段字符串追加到另一段字符串后面

使用注意事项

  1. 源字符串必须以 ‘\0’ 结束。
  2. 目标字符串中也得有 \0 ,否则没办法知道追加从哪里开始。
  3. 目标空间必须有足够的大,能容纳下源字符串的内容。
  4. 目标空间必须可修改。
  5. 返回值是目标空间的地址

字符串追加可以理解为两个过程:

  1. 找到目标字符串末尾的 ‘\0’
  2. 开始追加(其实就是字符串拷贝)
char* my_strcat(char* dst, const char* src)
{assert(dst && src);char* ret = dst;while (*dst){dst++;}while (*dst++ = *src++){;}return ret;
}

运行结果:

4. strcmp函数

strcmp函数(Compare two strings)的功能是字符串比较

  • 比较两个字符串是否相等
  • 如果相等,则返回0
  • 那么如何判断两个字符串? 比较两个字符串中对应位置上字符ASCII码值的大小。

使用注意事项

  1. 不是比较两个字符串的长度(极其易错
  2. 一般我只用来判断两个字符串是否相等,至于不相等时,比较字符之间大小,我感觉还没遇到很好的应用
int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while (*str1 == *str2){if (*str1 == '\0'){return 0;}str1++;str2++;}return *str1 - *str2;
}

运行结果:



5. strstr函数

strstr函数(Locate substring)的功能是查找子串

  • 在字符串str1中查找是否存在与str2相等的子串
  • 如果存在,则返回该地址(返回字符串str2在字符串str1中第⼀次出现的位置)
  • 如果不存在,则返回空指针

使用注意事项

  1. 如果要查找的子串为空串,则直接返回str1的地址

我们这里采用最直观,容易理解的暴力求解法

  1. 额外设立cur,dst,src三个指针
  2. 如果子串为空,则直接返回str1
  3. 如果str1为空,则直接返回NULL
  4. 如果不满足以上情况,则进入大循环:每次循环开始,让dst指向cur所在的位置,src指向str2(子串)
  5. 如果*dst == *src,则继续向后比较;如果不相等,则跳出小循环,判断src是否为 ‘\0’,如果为 ‘\0’ ,则代表匹配成功,返回地址cur
  6. 如果不为 ‘\0’,则代表当前位置往后没有可匹配的项,则cur++,继续重复以上循环
  7. 若以上循环结束,还没有找到对应子串,则返回NULL

是不是光看文字还不理解,我们来看图分析

首先,(假设dst是s1,src是s2),cur从a开始,s1和s2比较,不相等,再判断s2是否为’\0’,不为0,则cur++

cur再从b开始比较,s1和s2相等,则继续比较

直到s1和s2不相等,再判断s2是否为’\0’,不为0,则cur++

cur再从下一个b开始,同样重复以上步骤……

s2还是不为0,cur++

cur从第三个b开始,s1和s2比较。

这次,直到s1和s2不相等时,s2终于为’\0’,则代表匹配成功,返回地址cur!!!

//暴力求解
char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cur = str1;const char* dst = NULL;const char* src = NULL;if (*str2 == '\0'){return (char*)str1;}while (*cur){dst = cur;src = str2;while (*dst == *src){dst++;src++;}if (*src == '\0'){return (char*)cur;}cur++;}return NULL;
}

运行结果:



这种暴力求解的方法比较好理解,但效率却不是很高。其实还有一种高效求子串的方法——KMP算法,在后期会跟大家进行详细讲解。

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。

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

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

相关文章

Jmeter+influxdb+grafana监控平台在windows环境的搭建

原理:Jmeter采集的数据存储在infuxdb数据库中,grafana将数据库中的数据在界面上进行展示 一、grafana下载安装 Download Grafana | Grafana Labs 直接选择zip包下载,下载后解压即可,我之前下载过比较老的版本,这里就…

线性代数的艺术

推荐一本日本网友Kenji Hiranabe写的《线性代数的艺术》。这本书是基于MIT大牛Gilbert Strang教授的《每个人的线性代数》制作的。 虽然《线性代数的艺术》这本书仅仅只有12页的内容,就把线性代数的重点全画完了,清晰明了。 《线性代数的艺术》PDF版本&…

Python Opencv实践 - 全景图片拼接stitcher

做一个全景图片切片的程序Spliter 由于手里没有切割好的全景图片资源,因此首先写了一个切片的程序spliter。 如果有现成的切割好的待拼接的切片文件,则不需要使用spliter。 对于全景图片的拼接,需要注意一点,各个切片图片之间要有…

ubuntu环境删除qtcreator方法

文章目录 方法1方法2方法3参考不同的安装方法,对应不同的删除方法 方法1 apt-get或者dpkg 方法2 QtCreatorUninstaller 方法3 MaintenanceTool

STM32F10x进入低功耗模式

STM32F10x进入低功耗模式 目录 STM32F10x进入低功耗模式1 低功耗模式简介2 睡眠模式详解3 停止模式详解4 待机模式详解5 示例代码5.1 标准库函数定义5.2 进入低功耗模式参考代码 结束语 1 低功耗模式简介 在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续…

【Spring】 IoCDI

回顾 企业命名规范 大驼峰:BookDao(首字母都大写) 类名 小驼峰:bookDao(第一个字母小写) 方法名 蛇形:book_dao(小写下划线_) 数据库 串形:book-dao(小写连字符-) 项目文件夹 各种注解 学习Spring MVC, 其实就是学习各种Web开发需要⽤的到注解 a. RequestMapping: 路由…

【elementui】el-popover在列表里循环使用,取消的doClose无效解决办法

目录 一、需求效果二、代码详情html方法接口 一、需求效果 在使用elementui的Popover 弹出框时&#xff0c;需求是在table列表里使用&#xff0c;循环出来&#xff0c;无法取消。 二、代码详情 html <el-table-column v-if"checkPermission([admin,user:resetPass…

案例015:Java+SSM+uniapp基于微信小程序的校园防疫系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

人工智能带来的各方面影响

近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术在各个领域中的应用越来越广泛&#xff0c;已经开始对我们的生活方式、社会和经济结构产生深远的影响。 1.人工智能家庭化。人工智能技术使我们的生活变得更加便利和智能化。在家庭日常中&#xff0c;智能家居、智能…

C++学习之路(二)C++如何实现一个超简单的学生信息管理系统?C++示例和小项目实例

这个示例实现了一个简单的学生信息管理系统。它包括了学生类的定义&#xff0c;可以添加学生信息、显示所有学生信息&#xff0c;将学生信息保存到文件并从文件加载信息。通过这个示例&#xff0c;你可以了解到如何使用类、函数和文件操作来构建一个基本的信息管理系统。 一个简…

单片机串口通用收发代码

本篇博客大部分是自己收集和整理&#xff0c;借鉴了很多大佬的图片和知识点整理&#xff0c;如有侵权请联系我删除。本博客内容原创&#xff0c;创作不易&#xff0c;转载请注明 串口接收最后应有一定的协议&#xff0c;如发送一帧数据应该有头标志或尾标志&#xff0c;也可两个…

使用Pytorch从零开始构建GRU

门控循环单元 (GRU) 是 LSTM 的更新版本。让我们揭开这个网络的面纱并探索这两个兄弟姐妹之间的差异。 您听说过 GRU 吗&#xff1f;门控循环单元&#xff08;GRU&#xff09;是更流行的长短期记忆&#xff08;LSTM&#xff09;网络的弟弟&#xff0c;也是循环神经网络&#x…