​【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);
	else
		printf("找不到\n");

	ret = strstr(arr2, arr1);
	if (ret != NULL)
		printf("%s \n", ret);
	else
		printf("找不到\n");
	return 0;
}

结果如下:

 strstr的模拟实现

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

void Judge(char* p)
{
	if (p != NULL)
		printf("%s \n", p);
	else
		printf("找不到\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;
}

 结果如下:

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

日常的一些异常

Column ‘id’ in where clause is ambiguous 这个错误in where clause is ambiguous多半是因为多表查询的时候几个表中同时出现了某个相同的列名&#xff0c;而在查询条件WHERE后面又没有指定是那个表&#xff0c;而引起的,又或者是查询结果里面有两个相同的列名&#xff0c;…

[notice] A new release of pip is available: 23.2.1 -> 24.0

翻译之后&#xff1a;〔通知〕新版本的pip可用&#xff1a;23.2.1->24.0 就是说&#xff0c;你的pip版本需要从当前的 23.2.1 升级到最新版本 24.0&#xff0c;执行如下命令&#xff1a; cmd命令以管理员身份进入目录 ${Python}\Python3.12.1\Scripts下&#xff0c;执行 p…

好用便签:如何利用备忘录高效处理待办事项?

在快节奏的现代生活中&#xff0c;我们需要处理各种各样的待办事项&#xff0c;从个人生活琐事到工作任务。如何利用备忘录高效处理待办事项&#xff0c;成为了提升效率和生活质量的关键。一个合理的待办事项规划不仅能帮助我们明确目标&#xff0c;还能让我们更加有条不紊地应…

【软考高项】【教材知识梳理】- 17 - 第17章 - 项目干系人管理

一、基本问题 问题1&#xff1a;干系人登记册包括什么? a.身份信息&#xff1a;姓名、 组织职位、 地点、 联系方式&#xff0c; 以及在项目中扮演的角色。b.评估信息&#xff1a;主要需求、 期望、 影响项目成果的潜力&#xff0c; 以及干系人最能影响或冲击的项目生命周期阶…

知识付费App开发:重塑学习与知识的价值链

随着互联网的普及和信息爆炸的时代&#xff0c;人们对于知识的渴求从未如此强烈。然而&#xff0c;如何在海量的信息中筛选出有价值的内容&#xff0c;成为了摆在用户面前的一大难题。此时&#xff0c;知识付费App应运而生&#xff0c;为用户提供了一个高效、便捷的知识获取与交…

vscode 点击import引用的组件直接跳转方法

vs code。下载插件。 搜索名称&#xff1a;别名路径跳转

小程序--自定义组件

一、创建自定义组件 .js中注册Component函数 .json使用"component": true Component({}) {"component": true } 二、使用自定义组件 全局配置、页面配置均可&#xff0c;全局配置就写在app.json中&#xff0c;页面配置就写在页面对应的json中。 配置之后…

ncnn之三(补充):window环境下vs2022安装ncnn+protobuf

启动VS2022 下面的 x64 Native Tools Command Prompt for VS2022 protobuf git clone gitgithub.com:protocolbuffers/protobuf.git# 或者 下载 https://github.com/google/protobuf/archive/v3.11.2.zip cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPERelease -D…

node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染

文章目录 ⭐前言⭐ 功能设计与实现💖 node上传文件写入file_map映射表💖 vue3前端上传文件回显⭐ 效果⭐结束⭐前言 大家好,我是yma16,本文分享关于 node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染。 技术选型 前端:vite+vue3+antd 后端:node koa 数据库…

如何实现系统的高可用

一、SLA 当回答系统高可用时&#xff0c;就是回答这几个问题&#xff1a; 1、如何 评估系统高可用&#xff1f; 2、如何监控系统高可用&#xff1f; 3、如何保证系统高可用&#xff1f; 监控系统的内容&#xff1a; 基础设施监控有监控报警指标&#xff0c;分两部分内容&am…

CryptoPunks NFT 概览与数据分析

作者&#xff1a;stellafootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;CryptoPunks NFT Collection Dashboard CryptoPunks 于 2017 年推出&#xff0c;是 NFT 热潮的先驱&#xff0c;拥有 10,000 个独特的角色&#xff0c;这些角色已成为…

学习python的第二天

已经隔了8天没学习了&#xff0c;期间虽然有在开发那个业绩管理系统&#xff0c;但是很多时间都在网易云里emo&#xff0c;逛着被她拉黑的主页&#xff0c;用老版本app看她的听歌排行&#xff0c;魔怔了&#xff0c;她爱听的歌我都听遍了&#xff1b;她的排行榜一更新&#xff…

​LeetCode解法汇总105. 从前序与中序遍历序列构造二叉树

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给定两个整…

(十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用

前言 本节内容我们主要介绍在Jenkins流水线中&#xff0c;其构建过程中的一些构建策略的配置&#xff0c;例如通过远程http构建、定时任务构建、轮询SCM构建、参数化构建、Git hook钩子触发构建等&#xff0c;可根据不同的需求完成不同构建策略的配置。 正文 Throttle build…

如何使用CanaryTokenScanner识别Microsoft Office文档中的Canary令牌和可疑URL

关于CanaryTokenScanner CanaryTokenScanner是一款功能强大的Canary令牌和可疑URL检测工具&#xff0c;该工具基于纯Python开发&#xff0c;可以帮助广大研究人员快速检测Microsoft Office和Zip压缩文件中的Canary令牌和可疑URL。 在网络安全领域中&#xff0c;保持警惕和主动…

Failure [DELETE_FAILED_INTERNAL_ERROR]的解决办法

1.接上ADB 找到包名。 2 adb uninstall --user 0 com.subpos.client

2.20 day2 QT

自由发挥登录窗口的应用场景&#xff0c;实现一个登录窗口界面 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//窗口相关设置this->setWindowTitle("登入页面"); //设置 窗口 标题this->setWindowIcon(QIcon("D:…

ubuntu制作windows的u盘启动盘

概要&#xff1a; 本篇演示在ubuntu22.04中制作windows10的u盘启动盘 一、下载woeusb 1、下载woeusb 在浏览器中输入https://github.com/woeusb/woeusb/releases访问woeusb 点击红色矩形圈出来的部分&#xff0c;下载woeusb 2、安装wimtools wimtools是woeusb的一个必须的…

CentOS安装Docker(超详细)

文章目录 1.CentOS安装Docker1.1.卸载&#xff08;可选&#xff09;1.2.安装docker1.3.启动docker1.4.配置镜像加速 2.CentOS安装DockerCompose2.1.下载2.2.修改文件权限2.3.Base自动补全命令&#xff1a; 3.Docker镜像仓库3.1.简化版镜像仓库3.2.带有图形化界面版本3.3.配置Do…

Git基本指令

从远程拉代码 git clone gitgitlab-internal.wedobest.com.cn:dengyanhui/gittest.git添加所有文件到待上传列表 git add .提交 git commit -m message推送 git push获取现在的状态 git status更新本地代码 git pullgit拉取某一分支代码 git clone -b develop XXX本地删除…