字符串函数的模拟实现

引言:对于字符串来说,我们通常想要对其完成各种各样的目的,不管是排序还是查找都是最普遍的功能,而我们的C语言中也包含着一系列函数是为了实现对字符串的一些功能,今天我们就来介绍他们。


strlen函数:

求字符串的长度(也就是求一个字符串的'\0'前面有多少个字符)

#include<stdio.h>
#include<string.h>
int main(){char* str = "abcdef";int b = strlen(str);printf("%d\n", b);
return 0;
}

 

这个就是strlen最常用的,用来求一个字符串的长度,那么我们是否可以不用库函数,自己模拟一个strlen呢🤔
#include<stdio.h>
#include<string.h>
//方法一:计数法
size_t my_strlen1(char* str) {int count = 0;while (*str) {count++;str++;}return count;
}
int main(){char* str = "abcdef";int c = my_strlen1(str);printf("%d\n", c);
return0;
}

方法一:计数法,利用for循环,用count计数,当str遇到'\0'的时候循环结束,跳出循环,返回count的值。

#include<stdio.h>
#include<string.h>
//方法二:递归法
size_t my_strlen2(char* str) {if (*str == '\0')return 0;else return 1+my_strlen2(str+1);
}
int main() {char* str = "abcdef";int d = my_strlen2(str);printf("%d\n", d);
return 0;
}

 方法二:递归法,利用递归思想,当没有遇到'\0'的时候,就再次调用该函数,直到str遇到'\0',返回0,然后依次再重新返回,就计算出了字符串的长度。

#include<stdio.h>
#include<string.h>
//方法三:指针-指针
size_t my_strlen3(char* str) {char* p = str;while (*p != '\0') {p++;}return p - str;
}
int main(){char* str = "abcdef";int e = my_strlen3(str);printf("%d\n", e);return 0;
}

方法三:指针-指针,我们先将字符串的首元素地址记为str,再将首元素地址传给p,利用while循环找到最后一个元素的地址,当(结束地址-首元素地址)即为字符串长度。

 可以看我们四种方法的运行结果,都是可以正确的求出字符串‘acbdef的长度.

strcpy函数:

#include<stdio.h>
#include<string.h>
int main(){char arr1[20] = { 0 };char arr2[] = "Hello";strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}

这个函数的作用就是将arr2中的字符串拷贝到arr1中。那么我们该如何对他进行模拟实现呢🤔

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
char* my_strcpy(char* dest, const char* src) {char* ret = dest;while (*dest++ = *src++){;}return ret;
}
int main(){char arr1[20] = { 0 };char arr2[] = "Hello";//strcpy(arr1, arr2);my_strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}

 我们先将两个数组的首元素地址传给函数,因为最终要返回起始地址,所以先将dest给ret,然后运用while循环将src的每一项解引用后赋给dest,然后后置++再寻找下一个元素,直到src元素找到了'\0',然后循环跳出,返回起始地址ret。

我们把arr1打印出来可以看到确实是成功拷贝。 

strcmp函数:

比较的结果是:
如果str1>str2那么就返回一个>0的数 
如果str1<str2那么就返回一个<0的数
如果str1=str2那么就返回0
#include<stdio.h>
#include<string.h>
int main() {char arr1[] = { "abc" };char arr2[] = { "abdef" };int a = strcmp(arr1, arr2);if (a > 0) printf(">=");else printf("<");return 0;
}

这是一个简单的例子,因为d的ASC的值比c的ASC的值大,所以arr1<arr2,所以返回的是一个小于0的数,所以 打印出来的就是小于号。

那么我们来模拟实现实现一下这个函数

#include<stdio.h>
#include<string.h>
int my_strcmp(const char* dest, const char* src){while (*dest == *src) {if (*dest == 0) return 0;dest++;src++;}if (*dest > *src)return 1;else return -1;
}
int main() {char arr1[] = { "abc" };char arr2[] = { "abdef" };int a = my_strcmp(arr1, arr2);if (a > 0) printf(">=");else printf("<");return 0;
}

 首先,还是一样,先传值然后依旧是运用我们的while循环来进行遍历以及交换,当其中一个已经遍历完之后,会跳出while循环,然后开始判断当前元素谁大谁小,然后根据大小返回大于零还是小于零的数。

strcat函数:

#include<stdio.h>
#include<string.h>
int main() {char arr1[20] = { "abc"};char arr2[] = { "def" };//库函数自带的strcatstrcat(arr1, arr2);printf("%s\n", arr1);return 0;
}

 值得注意的是:

1、目标空间必须足够大,并且可以修改

2、目标空间中必须有\0,以便能够找到目标空间的末尾

3、源字符串中也得有\0,拷贝的时候要拷过去

那么我们如何对这个函数进行模拟实现呢🤔

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, char* src) {char* ret = dest;assert(dest && src);while (*dest != '\0') {dest++;}while (*dest++ = *src++) {;}return ret;
}
int main() {char arr1[20] = { "abc"};char arr2[] = { "def" };my_strcat(arr1, arr2);printf("%s\n", arr1);return 0;
}

 依然是传参,然后用第一个while循环找到目标空间中的\0然后,跳出循环,此时dest指向目标函数的末尾,然后进入第二个循环,src开始给dest进行赋值,直到src遇到\0,跳出循环,返回目标函数的起始地址,完成追加。

strstr函数: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main() {char arr1[] = { "abcdefghi" };char arr2[] = { "def" };char* ret = strstr(arr1, arr2);if (ret == NULL) {printf("找不到");}else printf("%s", ret);return 0;
}

strstr是字符串查找函数,我们给函数传两个字符串的时候,他会拿源函数去和目标函数进行匹配,如果目标函数中有原函数那么,就返回段函数的起始地址,如果找不到,那么就会返回NULL

那么我们该如何模拟实现这一函数呢🤔

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
const char* my_strstr(const char* str1, const char* str2) {const char* sp;const char* s1;const char* s2;assert(str1 && str2);if (*str2 == '\0') {return str1;}sp = str1;while (*sp) {s1 = sp;s2 = str2;while (*str1 && *str2 && *s1 == *s2) {s1++;s2++;}if (*s2 == '\0')return sp;sp++;}return NULL;
}
int main() {char arr1[] = { "abcdefghi" };char arr2[] = { "def" };char* ret = my_strstr(arr1, arr2);if (ret == NULL) {printf("找不到");}else printf("%s", ret);return 0;
}

 可以看到,我们模拟实现的函数成功的查找到了目标函数中的def,并且返回了找到它的起始位置。那么具体的实现我来详细的讲解一下。 

如图,我们用s1和s2进行比较,
1️⃣如果两个相同就各自+1比较下一个,那么按照这样进行下去,当str2为0的时候,就证明已经找到了,如果str1已经为0,str2还没有为0那么就证明,str1里找不到str2。
2️⃣如果两个不同就sp++,然后sp再赋值给s1,这样就不会使得s1一直向前++而找不到原来的位置了,s2也是一样,当sp赋值给s1的时候,str2也同时赋值给s2,让s2能回到起始位置。
这样一直对比下去,直到s1或s2指向0,函数结束。那我们这个函数的模拟就算实现了,但是其实这是个笨方法,效率不高,如果大家感兴趣的话,可以去了解了解kmp算法。

strerror函数:

是用来打印错误码的函数

 

 

strtok函数:

是用来将一段字符串进行分割的函数

 

#include<stdio.h>
#include<string.h>
int main() {char arr[] = "haohao@xuexi@tiantian.xiangshang";char* p = "@.";char* s = NULL;for (s = strtok(arr, p); s != NULL; s = strtok(NULL, p)) {printf("%s\n",s);}return 0;
}

我们这里可以看到,strtok将arr里的字符串给分隔开了,这个函数可以把指定参数替换成'\0',这样就可以将那些干扰的字符给去掉,并将其一一打印出来了。 

 好了,今天我就给大家分享到这里,感谢大家的观看!!!

 

 

 

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

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

相关文章

正则表达式 Regular Expression学习

该文章内容为以下视频的学习笔记&#xff1a; 10分钟快速掌握正则表达式_哔哩哔哩_bilibili正则表达式在线测试工具&#xff1a;https://regex101.com/, 视频播放量 441829、弹幕量 1076、点赞数 19330、投硬币枚数 13662、收藏人数 26242、转发人数 2768, 视频作者 奇乐编程学…

【visual studio 小技巧】项目属性->生成->事件

需求 我们有时会用到一些dll&#xff0c;需要把这些dll和我们生成的exe放到一起&#xff0c;一般我们是手动自己copy&#xff0c; 这样发布的时候&#xff0c;有时会忘记拷贝这个dll&#xff0c;导致程序运行出错。学会这个小技巧&#xff0c;就能实现自动copy&#xff0c;非…

AWS Lambda Golang HelloWorld 快速入门

操作步骤 以下测试基于 WSL2 Ubuntu 22.04 环境 # 下载最新 golang wget https://golang.google.cn/dl/go1.21.1.linux-amd64.tar.gz# 解压 tar -C ~/.local/ -xzf go1.21.1.linux-amd64.tar.gz# 配置环境变量 PATH echo export PATH$PATH:~/.local/go/bin >> ~/.bashrc …

Ubuntu20配置Mysql常用操作

文章目录 版权声明ubuntu更换软件源Ubuntu设置静态ipUbuntu防火墙ubuntu安装ssh服务Ubuntu安装vmtoolsUbuntu安装mysql5.7Ubuntu安装mysql8.0Ubuntu卸载mysql 版权声明 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明&#xff0c;所有版权属于黑马程…

STM32复习笔记(四):看门狗

目录 &#xff08;一&#xff09;简介 &#xff08;二&#xff09;IWDG IWDG的CUBEMX工程配置 IWDG相关函数&#xff08;非常少&#xff0c;所以直接贴上来&#xff09;&#xff1a; &#xff08;三&#xff09;WWDG &#xff08;一&#xff09;简介 看门狗分为独立看门…

【图像处理GIU】图像分割(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

PLL锁相环倍频原理

晶振8MHz&#xff0c;但是处理器输入可以达到72MHz&#xff0c;是因为PLL锁相环提供了72MHz。 锁相环由PD&#xff08;鉴相器&#xff09;、LP&#xff08;滤波器&#xff09;、VCO&#xff08;压控振荡器&#xff09;组成。 处理器获得的72MHz并非晶振提供&#xff0c;而是锁…

mysql八股

1、请你说说mysql索引&#xff0c;以及它们的好处和坏处 检索效率、存储资源、索引 索引就像指向表行的指针&#xff0c;是一个允许查询操作快速确定哪些行符合WHERE子句中的条件&#xff0c;并检索到这些行的其他列值的数据结构索引主要有普通索引、唯一索引、主键索引、外键…

代码随想录算法训练营第五十九天 | 647. 回文子串 516.最长回文子序列

1. 回文子串 647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; 一个子串左右两个元素相等&#xff0c;并且中间对称&#xff0c;才是回文子串 即 ij 时&#xff0c;[i1: j-1]对称 dp[i][j]&#xff1a; [i:j] 是否是回文字串 当 子串长度大于2 由 dp[i1][j-1] 推出…

mybatis项目启动报错:reader entry: ���� = v

问题再现 解决方案一 由于指定的VFS没有找&#xff0c;mybatis启用了默认的DefaultVFS&#xff0c;然后由于DefaultVFS的内部逻辑&#xff0c;从而导致了reader entry乱码。 去掉mybatis配置文件中关于别名的配置&#xff0c;然后在mapper.xml文件中使用完整的类名。 待删除的…

第P8周—YOLOv5-C3模块实现

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/Nb93582M_5usednAKp_Jtw) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制](https://mtyjkh.blog.csdn.net/)** >- **&#x1f680;…

基于遗传算法的新能源电动汽车充电桩与路径选择(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

数据结构与算法(三):栈与队列

参考引用 Hello 算法 Github&#xff1a;hello-algo 1. 栈 1.1 栈的概念 栈&#xff08;stack&#xff09;是一种遵循先入后出的逻辑的线性数据结构 可以将栈类比为桌面上的一摞盘子&#xff0c;如果需要拿出底部的盘子&#xff0c;则需要先将上面的盘子依次取出 如下图所示&…

【Pandas】数据分组groupby

本文目标&#xff1a; 应用groupby 进行分组对分组数据进行聚合,转换和过滤应用自定义函数处理分组之后的数据 文章目录 1. 数据聚合1.1 单变量分组聚合1.2 Pandas内置聚合方法1.3 聚合方法使用Numpy的聚合方法自定义方法同时计算多种特征向agg/aggregate传入字典 2. 数据转换…

Gmail 将停止支持基本 HTML 视图

根据 Google 支持文档的更新内容&#xff0c;Gmail 将从明年 1 月起停止支持基本 HTML 视图。 ▲ Gmai 基本 HTML 视图界面 目前网页版 Gmail 提供两个界面&#xff1a;基本 HTML 视图和标准视图。停止支持基本 HTML 视图后&#xff0c;当前打开经典模式的基本 HTML 视图模式 …

ChatGPT基础使用总结

文章目录 一、ChatGPT基础概念大型语言模型LLMs---一种能够以类似人类语言的方式“说话”的软件ChatGPT定义---OpenAI 研发的一款聊天机器人程序&#xff08;2022年GPT-3.5&#xff0c;属于大型语言模型&#xff09;ChatGPT4.0---OpenAI推出了GPT系列的最新模型ChatGPT典型使用…

【实操记录】Oracle数据整库同步至Apache Doris

本文是Oracle数据整库同步至Apache Doris实操记录&#xff0c;仅供参考 参考&#xff1a;https://cn.selectdb.com/blog/104 1、Oracle 配置 [rootnode1 oracle]# pwd /u01/app/oracle [rootnode1 oracle]# mkdir recovery_area [rootnode1 oracle]# chown -R oracle:dba re…

CleanMyMac X4.14.1最新版本下载

CleanMyMac X是一个功能强大的Mac清理软件&#xff0c;它的设计理念是提供多个模块&#xff0c;包括垃圾清理、安全保护、速度优化、应用程序管理和文档管理粉碎等&#xff0c;以满足用户的不同需求。软件的界面简洁直观&#xff0c;让用户能够轻松进行日常的清理操作。 使用C…

C/S架构学习之TCP的三次握手和四次挥手

TCP的三次握手&#xff1a;一定由客户端主动发起的&#xff0c;发生在建立连接的过程中。此过程发生在客户端的connect()函数和服务器的accept()函数之间。第一次握手&#xff1a;客户端向服务器发送一个带有SYN标志的数据包&#xff0c;表示客户端请求建立连接。并且客户端会选…

GEE土地分类——Property ‘B1‘ of feature ‘LE07_066018_20220603‘ is missing.错误

简介&#xff1a; 我正在尝试使用我在研究区域中选择的训练点对图像集合中的每个图像进行分类。就背景而言&#xff0c;我正在进行的项目正在研究陆地卫星生命周期内冰川面积的变化以及随后的植被变化。这意味着自 1984 年以来&#xff0c;我正在处理大量图像&#xff0c;每年一…