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

详解C语言string.h中常用的14个库函数(三)

string.h中的库函数
本篇博客继续讲解C语言string.h头文件中的库函数。本篇博客计划讲解3个函数,分别是:strstr, strtok, strerror。其中strstr函数我会用一种最简单的方式模拟实现。

strstr

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

strstr可以在str1中查找str2第一次出现的位置,并且返回一个指针指向该位置。如果找不到,就返回NULL指针。

比如:

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

输出结果:
在这里插入图片描述
由于返回了cccd第一次出现的位置,顺着该地址往后打印,就有了以上的结果。

这个函数的使用是非常简单的,它的难点在于如何实现。有一些比较复杂的算法,比如KMP算法,可以实现类似的功能,但是难度较大,不适合初学者,这里我使用一种暴力查找的思路来实现。

首先,搭出框架:

char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cp = str1;while (*cp){cp++;}
}

我的想法是,先用cp指针,指向str1的位置,然后使用该指针向后遍历str1这个字符串,看看能不能找到str2,如果找到了就返回cp指针。那每次如何查找呢?可以再定义2个指针s1和s2,s1从cp的位置向后遍历,s2从str2的位置向后遍历。

char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cp = str1;const char* s1 = str1;const char* s2 = str2;while (*cp){s1 = cp;s2 = str2;cp++;}
}

s1和s2指向的字符,如果相等,就遍历下一对,如果s2遇到了\0,就说明找到了。

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

strtok

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

strtok这个函数较为复杂,想要理解并且灵活使用,需要理解以下几点:

  1. strtok是用来分割字符串的。有些时候,我们想根据某些分隔符来分割一个字符串,就可以使用strtok。比如:"fish@qq.com",如果我们想根据@.这2个分隔符来分割该字符串,就可以分割成3个字符串,分别是:fish, qq, com
  2. strtok的第1个参数是待分割的字符串。第2个参数是分隔符的集合,即分隔符(一些字符)组合成的字符串。比如,如果我们想用@.来分割fish@qq.com这个字符串(假设把这个字符串存储到了字符数组arr中char arr[] = "fish@qq.com";),可以这么写:char* ret = strtok(arr, "@.");。其中"@."是由1个或多个分隔符组成的字符串。
  3. 如果“正常”调用该函数,即使用第2点的方式,strtok函数会找到字符串中的第1个分隔符出现的地方,把这个分隔符改成\0,并且返回由该分隔符分割的字符串(这个字符串在分隔符前面)。这么说有点抽象,以第2点的例子为例,strtok会在arr中找到第一个@,把@改成\0,此时arr数组存储的就是:"fish\0qq.com",函数会返回f的地址,此时如果使用printf以%s的格式打印这个返回的地址printf("%s\n", ret);,就会打印出fish。
  4. 如果调用该函数时,第一个参数为NULL指针,函数会从同一个字符串上次查找到的分隔符的位置开始向后找,找到下一个分隔符,然后返回以该分隔符分割的字符串(这个字符串在分隔符前面)。比如,假设已经像第2、3点所示调用过一次strtok函数了,如果再这么调用:ret = strtok(NULL, "@.");,函数就会找到.所在的位置,并把.改成\0,此时arr中存储的就是:"fish\0qq\0com",函数会返回第一个q的地址,此时以同样的方式printf("%s\n", ret);打印这个返回值,就会打印qq。同理,再调用一次ret = strtok(NULL, "@.");,然后再打印printf("%s\n", ret);就会打印出com。
  5. 如果函数没有找到下一个标记,就会返回NULL指针。

所以,根据以上知识点,如果我想要分割一个字符串"hello@world.nihao-shijie@this+is@a.test",可以使用一个循环来搞定。注意,一般来说,我们都会先把这个字符串拷贝一份,再来做分割,因为strtok函数会改变原字符串。

#include <stdio.h>
#include <string.h>int main()
{char arr[] = "hello@world.nihao-shijie@this+is@a.test";char bak[100] = { 0 };strcpy(bak, arr);const char* sep = "@.+-";char* ret = strtok(arr, sep);while (ret){printf("%s\n", ret);ret = strtok(NULL, sep);}return 0;
}

只有第一次调用是“正常”调用,其他每次调用第一个参数都传NULL指针,这样就会从上次找到的位置接着向后找。哪次没有找到就会返回NULL指针,跳出循环。

输出结果:
在这里插入图片描述

strerror

char * strerror ( int errnum );

strerror函数会返回错误码对应的错误信息。使用起来非常简单,比如我强行制造一个错误,让malloc函数开辟很大一块空间。当然,strerror智能检测库函数调用时的错误。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>int main()
{size_t n = -1; // 制造一个很大的数int* p = (int*)malloc(n);if (p == NULL){printf("malloc: %s\n", strerror(errno));return 1;}// ...free(p);p = NULL;return 0;
}

在这里插入图片描述

可以发现,malloc函数开辟空间失败时,使用strerror,把错误码errno转换成了一个字符串,并且返回这个字符串的起始位置。顺着这个位置打印,就打印出了错误信息:“Not enough space”。

errno是一个全局变量,如果库函数调用失败,就会设置错误码,而strerror就可以把该错误码转换成错误信息。注意,errno的使用需要引用头文件errno.h。

当然,如果只想打印错误信息,可以直接使用perror函数,比如以上程序就可以把printf("malloc: %s\n", strerror(errno));换成perror("malloc");。各位可以自行验证,以上2句代码是完全等价的。

总结

  1. strstr函数可以在一个字符串中查找子串,如果找到,就返回第一次出现的位置;如果找不到返回NULL指针。
  2. strtok函数可以分割一个字符串。如果“正常”调用,即第一个参数不为NULL,就会去找分隔符第一次出现的位置;如果第一个参数为NULL,就会从上一次找到的位置开始向后找。
  3. strerror可以把错误码转换成错误信息。当库函数调用出现错误时,编译器会把错误码保存到errno这个全局变量中,而strerror可以把errno对应的错误码转换成错误信息。

感谢大家的阅读!

相关文章:

详解C语言string.h中常用的14个库函数(三)

本篇博客继续讲解C语言string.h头文件中的库函数。本篇博客计划讲解3个函数&#xff0c;分别是&#xff1a;strstr, strtok, strerror。其中strstr函数我会用一种最简单的方式模拟实现。 strstr char * strstr ( const char * str1, const char * str2 );strstr可以在str1中查…...

无人机视频与GIS融合三维实景怎么实现?

无人机视频与GIS融合三维实景怎么实现?无人机三维GIS作为一项新兴的测绘重要手段&#xff0c;具有续航时间长、成本低、机动灵活等优点&#xff0c;为城市的规划建设带来极大便利。 那么此项技术有什么样的特点呢?下面智汇云舟就带大家一起来了解一下。 三维是将采集以及经运…...

瞬间让你效率提高一倍的高效学习方法

方法不对&#xff0c;努力白费&#xff1b;方法对了&#xff0c;事半功倍&#xff01;在学习的过程中我们会遇到各种困难与阻碍&#xff0c;如何发现并优化自己的学习方法就变得尤为重要。高效学习方法是指通过科学的、有效的方法来提高学习效率&#xff0c;实现更好的学习成果…...

442. 数组中重复的数据|||41. 缺失的第一个正数|||485. 最大连续 1 的个数

442. 数组中重复的数据 题目 给你一个长度为 n 的整数数组 nums &#xff0c;其中 nums 的所有整数都在范围 [1, n] 内&#xff0c;且每个整数出现 一次 或 两次 。请你找出所有出现 两次 的整数&#xff0c;并以数组形式返回。 你必须设计并实现一个时间复杂度为 O(n) 且仅…...

中国地图标准坐标和投影参数

目录 一、地理坐标 二、投影坐标 三、ArcGIS投影变换 四、说明 一、地理坐标 GCS_Krasovsky_1940&#xff08;克拉索夫斯基_1940椭球体&#xff09; 具体参数如下图&#xff1a; 每个国家或地区都有各自的基准面&#xff0c;我们通常所说的北京54坐标系、西安80坐标系实际上…...

CNN中卷积层、池化的计算公式

卷积计算公式 1、卷积层输入特征图(input feature map)的尺寸为&#xff1a;(batch_size,Channel,H,W) H(input)表示输入特征图的高 W(input)表示输入特征图的宽 C(input)表示输入特征图的通道数&#xff08;如果是第一个卷积层则是输入图像的通道数&#xff0c;如果是中间…...

基类派生类多态虚函数?

通常在层次关系的根部有一个基类&#xff0c;其他类则直接或间接的从基类继承而来&#xff0c;这些继承得到的类称为派生类。基类负责定义在层次关系中所有类共同拥有的成员&#xff0c;而每个派生类定义各自特有的成员。 成员函数与继承派生类可以继承其基类的成员, 然而有时…...

像素是什么

像素分为设备像素和设备无关像素。 下面说说来龙去脉。 一、显示器 显示图像的电子设备。 &#xff08;一&#xff09;显示器种类 1.LCD LCD&#xff08;Liquid crystal display&#xff09;&#xff0c;是液体晶体显示&#xff0c;也就是液晶显示器&#xff0c;LCD具有功耗低…...

NAT转换

目录标题 NAT&#xff1a;网络地址转换&#xff08;cisco篇&#xff09;一对一&#xff08;静态&#xff09;一对多&#xff08;动态&#xff09;多对多&#xff08;动、静均可&#xff09;端口映射&#xff08;静态&#xff09; nat:网络地址转换&#xff08;华为篇&#xff0…...

设计模式:创建者模式 - 单例模式

文章目录 1.介绍2.单例模式的结构3.单例模式的实现&#xff08;饿汉、懒汉&#xff09;饿汉式-方式1&#xff08;静态变量方式&#xff09;饿汉式-方式2&#xff08;静态代码块方式&#xff09;懒汉式-方式1&#xff08;线程不安全&#xff09;懒汉式-方式2&#xff08;线程安全…...

C++语言亚马逊国际获取AMAZON商品详情 API接口(

跨境电子商务是一种全新的互联网电商模式&#xff0c;运用电子化方式促成线上跨境交易&#xff0c;利用跨境物流运送商品&#xff0c;有利于打破传统的贸易格局&#xff0c;成为新的经济增长点。对我国来说&#xff0c;跨境电商平台正用一种全新的力量改变我国产业链的结构&…...

在程序里面执行system(“cd /某个目录“),为什么路径切换不成功?

粉丝提问&#xff1a; 彭老师&#xff0c;问下&#xff0c;在程序里面执行system(“cd /某个目录”)&#xff0c;这样会切换不成功&#xff0c;为啥呢 实例代码&#xff1a; 粉丝的疑惑是明明第10行执行了cd /media操作&#xff0c; 为什么12行执行的pwd > test2.txt 结…...

c++ 对类与对象的基础框架+完整思维导图+基本练习题+深入细节+通俗易懂建议收藏

绪论 上一章&#xff0c;我们将c入门的基础知识进行了学习&#xff0c;本章其实才算真正的跨入到c开始可能比较难&#xff0c;但只有我们唯有不断的前进&#xff0c;才能斩断荆棘越过人生的坎坷&#xff01; 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看&…...

关于Open Shift(OKD) 中应用管理部署的一些笔记

写在前面 因为参加考试&#xff0c;会陆续分享一些 OpenShift 的笔记博文内容为介绍 openshift 不同的创建应用的方式&#xff0c;包括&#xff1a; 基于 IS 创建应用基于镜像创建应用基于源码和 image 创建应用基于源码和 IS 创建应用基于模板创建应用 学习环境为 openshift v…...

【linux】对于权限的理解

权限 Linux权限的概念用户之间的切换 Linux权限管理文件权限操作文件的人Linux文件默认权限的设置权限掩码 所属组/其他删除拥有者创建的文件文件拥有者、所属组的修改修改文件拥有者修改文件所属组一次性修改拥有者和所属组 目录的执行权限 Linux权限的概念 首先&#xff0c;…...

测试人必备技能:如何进行WebSocket接口测试?

目录 前言 WebSocket介绍 HTTP与WebSocket的区别 二者关系 WebSocket测试方法 使用Postman 使用Jmeter 使用Python 结语 前言 随着Web应用的日益普及&#xff0c;WebSocket作为一种全双工通信协议&#xff0c;在移动端、游戏、视频会议等方面得到广泛应用。 而对于需…...

【Android FrameWork (三)】- SystemServer

文章目录 知识回顾启动第一个流程initZygote的流程 前言源码分析1.system_server2.SystemServer.main3,startBootstrapServices4,startService 拓展知识LoadApkcontext 对于Android context 大家是怎么理解的&#xff1f;LocalServices.java: addServece方法中 ArrayMap和HashM…...

Docker容器部署及基本使用

文章目录 一、环境初始化配置二、安装Docker三、优化配置四、基础命令 一、环境初始化配置 1、关闭防火墙 systemctl stop firewalld systemctl disable firewalldsetenforce 0sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config sed -i s/SELINUXenforcing/S…...

【机智云物联网低功耗转接板】+模拟MCU快速上手

GE211是机智云自研的定制化转接板&#xff0c;使用 ESP32-C3-WROOM-02 通讯模块&#xff0c;适用于白色智能家电等设备应用。 转接板已经烧录了机智云连云的最新GAgent固件&#xff0c;所以不需要烧写任何软件就可以快速上手使用。 GE211板卡带有一个串口&#xff0c;一般是把这…...

ai免费写作在线平台-ai免费伪原创文章生成器软件

ai伪原创能检测出来吗 人工智能技术可以检测伪原创&#xff0c;但是不是所有的伪原创都可以被检测出来。 现在有许多自然语言处理&#xff08;NLP&#xff09;算法和技术可以用来检测伪原创内容&#xff0c;例如文本相似度比较算法&#xff0c;语气分析算法等。这些算法可以检…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...