当前位置: 首页 > news >正文

​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】

欢迎来CILMY23的博客喔,本期系列为​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】,图文讲解各种字符串函数,带大家更深刻理解C语言中各种字符串函数的应用,感谢观看,支持的可以给个赞哇。 

前言

上一篇说到,有不受长度限制的字符串函数,它们分别是strcpy,strcat,strcmp,为了方便我们想要长度限制,C语言提供了三个加n的函数,strncpy,strncat,strncmp函数,本期将了解剩下的三个字符串函数,它们分别是strstr,strtok,strerror。

目录

 一、strstr

二、strtok

三、strerror


 一、strstr 

 strstr函数可以在cplusplus中查到,strstr - C++ Reference (cplusplus.com)

函数原型如下:

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

 函数介绍如下:

返回值和使用案例:

 

strstr的使用

 strstr函数功能就是返回str2在str1中第一次出现的位置,如果str2没有在str1中出现,就返回NULL

#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "hello CILMY23";char arr2[] = "C";char* ret = strstr(arr1, arr2);if (ret != NULL)printf("%s \n", ret);elseprintf("找不到\n");ret = strstr(arr2, arr1);if (ret != NULL)printf("%s \n", ret);elseprintf("找不到\n");return 0;
}

结果如下:

 strstr的模拟实现

为了检验自己写的是否对不对,我们拿出几组的测试用例

void Judge(char* p)
{if (p != NULL)printf("%s \n", p);elseprintf("找不到\n");
}int main()
{char arr1[] = "hello CILMY23";char arr2[] = "C";char arr3[] = "lllC";char arr4[] = "This is a simple string";char arr5[] = "";char* ret = strstr(arr1, arr2);Judge(ret);ret = strstr(arr2, arr1);Judge(ret);ret = strstr(arr3, arr1);Judge(ret);ret = strstr(arr3, arr2);Judge(ret);ret = strstr(arr1, arr3);Judge(ret);ret = strstr(arr2, arr3);Judge(ret);ret = strstr(arr4, "simple");Judge(ret);ret = strstr(arr1, arr5);Judge(ret);return 0;
}

 这组测试用例的结果是:

思路一 

 思路解析:

遍历源字符串,找到与字符串2首字母相同的字符,进入循环2,但在进入之前需要保存一份当前位置,然后我们再去利用新开辟出来的两个指针去遍历两个字符串,如果有不相等的地方,那么字符串肯定是走不到尾巴的,也就是不可能等于'\0',此时继续遍历字符串1,直到字符串1遍历结束,完成整个字符串的查找,没有就返回NULL。

char * my_strstr(const char* str1,const char* str2)
{assert(str1 && str2);char* str3 = NULL;char* str4 = NULL;while (*str1 != '\0'){		str4 = str2;str3 = str1;while(*str3 == *str4 && *str3 && *str4){str3++;str4++;}if (*str4 == '\0')return str1;str1++;}return NULL;
}

 逻辑图如下:

代码优化

代码优化解析:

1.我们并不希望在遍历字符串的时候所有的值都被修改,包括我后续返回的地址,所以全部都可以用const修饰

2.当我第二个字符串为空的时候,返回字符串1的地址,就相当于你让我在一个字符串里找什么都没有的东西,库里设计是返回第一个字符串地址

3.我们不希望改变原有的地址,str1,和str2,所以再创建一个指针变量用来代替上述str1的使用 

const char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cp = str1;const char* s1 = NULL;const char* s2 = NULL;if (*str2 == '\0'){return str1;}while (*cp){s1 = cp;s2 = str2;while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0'){s1++;s2++;}if (*s2 == '\0'){return cp;}cp++;}return NULL;
}

根据测试用例跑出来的结果如下: 

 

二、strtok

了解strtok函数之前,我们要先了解一个概念,相信大家都看过IP地址, 计算机网络通信协议是用的IP协议,于是链接进互联网的设备会有一个IP地址,这个IP地址,IP地址通常用“点分十进制”表示成(a.b.c.d)的形式

例如:192.168.1.23

 IP地址的本质还是一个整数,因为不好记,才有了点分十进制的表示方式。

那如果我们想把这个IP地址的每个数字取出来就会用到,strtok这个函数。又或者你想把邮箱的域名,邮箱名,域名后缀取出来也会用到strtok这个函数。其中@和.这种东西我们就把它称作分隔符

strtok网站以及函数原型如下:

strtok - C++ Reference (cplusplus.com)

char * strtok ( char * str, const char * delimiters );

 strtok的函数介绍:

 

返回值和使用案例: 

strtok的使用

#include<stdio.h>
#include<string.h>int main()
{char str1[] = "hello.CIL.MY@23";char buf[60] = { 0 };strcpy(buf, str1);char* p = ".@";char* r = NULL;for (r = strtok(buf, p); r != NULL; r = strtok(NULL, p)){printf("%s", r);}return 0;
}

打印结果如下:

 strtok总结:

•    sep参数指向⼀个字符串,定义了用作分隔符的字符集合
•    第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标记
•    strtok函数找到str中的下⼀个标记,并将其用\0 结尾,返回⼀个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使⽤strtok函数切分的字符串⼀般都是临时拷贝的内容并且可修改。)
•    strtok函数的第⼀个参数不为NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串中的位置。
•    strtok函数的第⼀个参数为NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标记。
•    如果字符串中不存在更多的标记,则返回NULL 指针。

三、strerror

strerror 的网址:

strerror - C++ Reference (cplusplus.com) 

函数原型:

char * strerror ( int errnum );

函数介绍如下: 

函数的功能及使用案例:

 函数解析:

strerror是一个返回错误码所对应的错误字符串的起始地址,在C语言的库函数中设计错误码,当我们库函数在调用过程中发生错误信息了,要记录下来,这就是错误码。是一个编码。

当库函数调用失败的时候,会将错误码记录到变量errno当中,errno是C语言中的一个全局变量。

strerror的使用

int main()
{int i = 0;for (i = 0; i < 10; i++){printf("%d:%s \n",i,strerror(i));}return 0;
}

 结果如下:

 

相关文章:

  • AIGC算法研究团队整理汇总[持续更新]
  • 基于AI将普通RGB图像转换为苹果Vision Pro支持的空间照片
  • gradle 整合springboot druid flyway 并实现数据库密码加密
  • Orange3数据预处理(列选择组件)数据角色及类型描述
  • Odoo17 不再支持视图中的attrs和states
  • 2024.02.23作业
  • 9.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-接管游戏连接服务器的操作
  • LeetCode 2960.统计已测试设备
  • 哈希表在Java中的使用和面试常见问题
  • 【C语言】linux内核ipoib模块 - ipoib_ib_post_receive
  • leetcode hot100 买卖股票最佳时机3
  • 4.4 MySQL存储
  • Springboot集成Druid实现监控功能
  • 【力扣hot100】刷题笔记Day13
  • BlackberryQ10 是可以安装 Android 4.3 应用的,Web UserAgent 版本信息
  • [译]CSS 居中(Center)方法大合集
  • Javascript Math对象和Date对象常用方法详解
  • JavaScript设计模式与开发实践系列之策略模式
  • Java多线程(4):使用线程池执行定时任务
  • js面向对象
  • Less 日常用法
  • linux学习笔记
  • ReactNative开发常用的三方模块
  • storm drpc实例
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 排序算法学习笔记
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 译有关态射的一切
  • ()、[]、{}、(())、[[]]命令替换
  • (2)STL算法之元素计数
  • (2.2w字)前端单元测试之Jest详解篇
  • (k8s中)docker netty OOM问题记录
  • (vue)页面文件上传获取:action地址
  • (九十四)函数和二维数组
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .net 简单实现MD5
  • .net 使用ajax控件后如何调用前端脚本
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .Net中ListT 泛型转成DataTable、DataSet
  • .NET中winform传递参数至Url并获得返回值或文件
  • .vue文件怎么使用_vue调试工具vue-devtools的安装
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • :not(:first-child)和:not(:last-child)的用法
  • @ModelAttribute使用详解
  • @Query中countQuery的介绍
  • [ vulhub漏洞复现篇 ] Hadoop-yarn-RPC 未授权访问漏洞复现
  • [ 转载 ] SharePoint 资料
  • []T 还是 []*T, 这是一个问题
  • [20161101]rman备份与数据文件变化7.txt
  • [C]整形提升(转载)
  • [C++]C++基础知识概述
  • [hdu 3652] B-number
  • [HJ56 完全数计算]
  • [JavaScript]_[初级]_[关于forin或for...in循环语句的用法]