珠海企业网站建设报价/国际最新十大新闻事件
【C语言】——字符串函数的使用与模拟实现(下)
- 前言
- 五、长度受限类字符串函数
- 六、 s t r s t r strstr strstr 函数
- 6.1、函数功能
- 6.2、函数的使用
- 6.3、函数的模拟实现
- (1)解题思路
- (2)代码实现
- 七、 s t r t o k strtok strtok 函数
- 7.1、函数功能
- 7.2、函数的使用
- 八、 s t r e r r o r strerror strerror 函数
- 8.1、函数功能
- 8.2、函数的使用
- 九、 p e r r o r perror perror 函数
前言
上一篇文章:【C语言】——字符串函数的使用与模拟实现(上)中,我曾详细介绍了: s t r s t r strstr strstr、 s t r c p y strcpy strcpy、 s t r c a t strcat strcat、 s t r c m p strcmp strcmp 这四个函数及其模拟实现,接下来,让我们继续学习字符串相关的函数吧。
五、长度受限类字符串函数
5.1、 s t r n c p y strncpy strncpy 函数
功能:将源字符串的前 n u m num num 个字符拷贝到目标字符串中
- 如果源字符串长度小于 n u m num num,则拷贝完源字符创后,在目标空间后面
追加\0
,直到 n u m num num 个。 - 如果源字符串长度大于 n u m num num,则在拷贝完源字符串前 n u m num num 个字符后,末尾
不会
自动补 ‘\0’
5.2、 s t r n c a t strncat strncat 函数
功能:将源字符串的前 n u m num num个字符追加至目标字符串的末尾
- 如果源字符串长度大于 n u m num num,追加前 n u m num num 个字符并在后面
补'\0'
- 如果源字符串长度小于 n u m num num,追加整个源字符串并
补'\0'
。(只补一个
,不会一直补到 n u m num num 个)
5.3、 s t r n c m p strncmp strncmp 函数
功能:比较 s t r 1 str1 str1 和 s t r 2 str2 str2 的前 n u m num num 个字符,如果相等就继续往后比较,最多比较 n u m num num 个字符,如果提前发现不一样,提前结束,大的字符所在的字符串大于另外一个
,如果 n u m num num 个字符都相等
,就返回 0
。
六、 s t r s t r strstr strstr 函数
6.1、函数功能
功能:查找字符串 s t r 1 str1 str1 中是否包含字符串 s t r 2 str2 str2 的内容,如果有,返回第一次出现的地址,如果没有,返回空指针。
需要注意的是:字符串的比较匹配不包含 ‘\0’,以 ‘\0’ 作为结束标志。
6.2、函数的使用
#include<stdio.h>
#include<string.h>int main()
{char str1[] = "This is a simple string";char* str2;str2 = strstr(str1, "simple");printf("%s\n", str2);for (int i = 0; i < strlen("simple"); i++){printf("%c", str2[i]);}printf("\n");str2 = strstr(str1, "are");printf("%s\n", str2);return 0;
}
运行结果:
6.3、函数的模拟实现
(1)解题思路
( i ) (i) (i) 首先,我们来看最简单的情况:在 “ a b c d e f abcdef abcdef” 中找 “ c d e cde cde”
- 我们先来看上左图: s t r 1 str1 str1 和 s t r 2 str2 str2 指向两个字符串起始位置,是我们传入的值,这里我额外创建指针 c p cp cp 变量,用指针 c p cp cp 来遍历 s t r 1 str1 str1 数组。
- 看上右图:当指针 c p cp cp 指向字符 ‘ c c c’ 时,发现字符 ‘ c c c’ 与 s t r 2 str2 str2的首字符相同。
为进一步确认
, c p cp cp 与 s t r 2 str2 str2同时遍历
后面的字符,每遍历一次,相比较一次。当 s t r 2 str2 str2 遍历完字符串,比较结束,发现所比较的字符全部相等,即找到 s t r 1 str1 str1 中的 s t r 2 str2 str2。
上面的思路看起来是可行的,但是还是存在这很大的问题:
- 函数要求的是返回地址,也就是返回上面 ‘ c c c’ 字符的地址,可是 c p cp cp 指针跑后面去了,怎么返回他的地址呢?
- 想象一下,当 c p cp cp 开始比较时,与 s t r 2 str2 str2 的前几个字符是相等的,但后面不相等,这时是不是
又要从‘c’的下一个字符重新开始比较
,但是 c p cp cp 与 s t r 2 str2 str2都跑后面去
了,还怎么找到下一个字符呢?
( i i ) (ii) (ii) 下面,我们来考虑复杂一点的情况:在 “ a b b b c d f abbbcdf abbbcdf” 中找 “ b b c bbc bbc”
鉴于上述情况出现的两种问题,我们再额外创建两个指针变量 s 1 s1 s1 与 s 2 s2 s2,他们负责实现字符的逐个比较
,而 c p cp cp 与 s t r 2 str2 str2用于记录开始比较的起始位置
。这样,当 s 1 s1 s1 与 s 2 s2 s2 只有部分相等时,依然可以找到下一个字符重新开始比较
( i i i ) (iii) (iii) 再看最后一种情况:如果找不到怎么办?例如:在 “ a b b b c abbbc abbbc” 中找 “ b b c c bbcc bbcc”
其实,中不到的情况的解决思路与第二种情况时一样
的,不同的是,当 c p cp cp 遍历完
整个 s t r 1 str1 str1 字符串(即 c p cp cp 指向 \0)还没找到时,即 s t r 1 str1 str1 中不存在 s t r 2 str2 str2 字符串,返回空指针
(2)代码实现
char* my_strstr(const char* str1, const char* str2)
{//创建指针变量:cp、s1、s2//因为并不知道什么时候开始比较,s1、s2先置空const char* cp = str1;const char* s1 = NULL;const char* s2 = NULL;//特殊情况:当str2为空时,返回整个str1if (str2 == NULL){return (char*)str1;}//循环,当cp指向‘\0’时,退出,表面没找到while (*cp){//进入逐个比较if (*cp == *str2){//给s1、s2赋值,让他们进行比较s1 = cp;s2 = str2;//如果他们相等,并且不等于‘\0’比较继续while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2){s1++;s2++;}//退出比较时,表明遇到不一样的字符//这时有两种情况//退出后,当s2指向‘\0’时,表明成功找到//当s2不是指向‘\0’,表示并不是要找的字符串if (*s2 == '\0'){return (char*)cp;}}cp++;}//整个循环结束,表明没找到,返回空指针return NULL;}
七、 s t r t o k strtok strtok 函数
7.1、函数功能
函数功能:将 s t r str str 字符串 以字符 d e l i m i t e r s delimiters delimiters 作为分隔符
,分割成若干段
。
- s t r str str 参数表示
要分割的字符串
- d e l i m i t e r s delimiters delimiters 参数表示
分隔符
,分隔符可以是多个
- s t r t o k strtok strtok 函数找到 s t r str str 中的下一个标记,并将其用 \0 结尾,返回一个
指向这段字符串的指针
- s t r t o k strtok strtok 函数会
改变
被操作的字符串,所以在使用 s t r t o k strtok strtok 函数切分的字符串一般都是临时拷贝
的内容,并且可以被修改
- s t r t o k strtok strtok 函数的第一个参数不为NULL时,函数将
找到
s t r str str 中的第一个标记
, s t r t o k strtok strtok 函数将保存它在字符串中的位置
- s t r t o k strtok strtok 函数的第一个参数为NULL,函数将在同一个字符串中
被保存的位置开始
,查找下一个标记
- 如果字符串
不存在更多的标记
,则返回NULL指针
7.2、函数的使用
像 happy@qq.com,现在我想将 happy、qq、com 这三段单独提取出来,这时就可以使用 s t r t o k strtok strtok函数
#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "happy@qq.com";char arr2[30];const char* sep = "@.";strcpy(arr2, arr1);char* ret = NULL;ret = strtok(arr2, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);return 0;
}
运行结果:
可以看到, s t r t o k strtok strtok 函数很奇怪,只有第一次调用他是传的是要切割的字符串 a r r 2 arr2 arr2,之后调用都是传 NULL。
这是因为该函数每一次调用该函数都把当前找的这个标记的结束位置记住
,这样下次再调用该函数就能从上次保存的位置开始找下一个标记
当第四次调用该函数时,因为已经找到结束位置
,因此函数返回空指针。
注:这里只是示范,实际上是不允许这样打印的
当然,上面的代码有很大的改进空间
,因为我们往往不知道有几个分隔符,这时我们可以用一种巧妙的写法
#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "happy@qq.com@happy@qq.com";char arr2[30];const char* sep = "@.";strcpy(arr2, arr1);char* ret = NULL;for (ret = strtok(arr2, sep); ret != NULL; ret = strtok(NULL, sep)){printf("%s\n", ret);}return 0;
}
我们来分析一下for (ret = strtok(arr2, sep); ret != NULL; ret = strtok(NULL, sep))
这个循环:
- 首先是初始化部分
ret = strtok(arr2, sep)
:将strtok(arr2, sep)
的值传给 r e t ret ret 变量 - 接着是判断部分
ret != NULL
:当 r e t ret ret 不为空时,循环继续,即打印该段字符串;当返回值为空,表示已经分割完字符串,循环结束 - 最后是调整部分
ret = strtok(NULL, sep)
:将strtok(NULL, sep)
的返回值赋给 r e t ret ret 变量 - 这个代码巧妙在 s t r t o k strtok strtok 函数要求第一次传的是字符串,而之后传的是NULL,这里完美运用了 f o r for for 循环的特点:
先初始化,并且初始化只执行一次,调整语句执行多次
。
运行结果:
八、 s t r e r r o r strerror strerror 函数
8.1、函数功能
功能:把参数部分错误码对应的错误信息的字符串地址返回来
在不同的系统和 C 语言标准库中都规定了一些错误码
,一般放在 < e r r n o . h errno.h errno.h> 这个头文件中说明。
C语言程序启动时就会使用一个全面的变量
e r r n o errno errno 来记录程序当前的错误码,只不过程序启动时 e r r n o errno errno 是 0,表示没有错误
。
当我们在使用标准库中的函数的时候发生了某种错误
,就会将对应的错误码,放在errno中
,而一个错误码的数字是整数,因此很难理解是什么意思,所以每个错误码都是有对应的错误信息的。 s t r e r r o r strerror strerror 函数就可以将错误对应的错误信息字符串的地址返回
。
8.2、函数的使用
我们打印 0 − 10 0-10 0−10 这些错误码所对应的信息
#include<errno.h>
#include<string.h>
#include<stdio.h>int main()
{int i = 0;for (i = 0; i <= 10; i++){printf("%s\n", strerror(i));}return 0;
}
运行结果:
再比如:我们以读的方式打开一个不存在的文件,让其返回错误信息
#include<errno.h>
#include<string.h>
#include<stdio.h>int main()
{FILE* pFile;pFile = fopen("unexist.ent", "r");if (NULL == pFile){printf("Error opening file unexist.ent: %s\n", strerror(errno));}return 0;
}
运行结果:
九、 p e r r o r perror perror 函数
功能: p e r r o r perror perror 函数相当于 p e i n t f + s t r e r r o r peintf+strerror peintf+strerror,它会打印完参数本分的字符串内容
后,再打印一个冒号
和一个空格
,再打印错误信息
。
例如:
#include<errno.h>
#include<string.h>
#include<stdio.h>int main()
{FILE* pFile;pFile = fopen("unexist.ent", "r");if (NULL == pFile){perror("Error opening file unexist.ent");}return 0;
}
运行结果:
好啦,本期关于部分字符串函数的介绍及模拟实现就介绍到这里啦,希望本期博客能对你有所帮助,更多关于字符串的函数还请收看下一期。同时,如果有错误的地方请多多指正,让我们在C语言的学习路上一起进步!
相关文章:

【C语言】——字符串函数的使用与模拟实现(下)
【C语言】——字符串函数的使用与模拟实现(下) 前言五、长度受限类字符串函数5.1、 s t r n c p y strncpy strncpy 函数5.2、 s t r n c a t strncat strncat 函数5.3、 s t r n c m p strncmp strncmp 函数 六、 s t r s t r strstr strstr 函数6.1、函…...

mac安装nvm详细教程
0. 前提 清除电脑上原有的node (没有装过的可以忽略)1、首先查看电脑上是否安装的有node,查看node版本node -v2、如果有node就彻底删除nodesudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node.*}2、保证自己的电脑上有安装git,不然下载n…...

上线流程及操作
上节回顾 1 搜索功能-前端:搜索框,搜索结果页面-后端:一种类型课程-APIResponse(actual_courseres.data.get(results),free_course[],light_course[])-搜索,如果数据量很大,直接使用mysql,效率非常低--》E…...

MobX入门指南:快速上手状态管理库
一、什么是MobX MobX 是一个状态管理库,它可以让你轻松地管理应用程序的状态,并且可以扩展和维护。它使用观察者模式来自动传播你的状态的变化到你的 React 组件。 二、安装及配置 安装 MobX 和 MobX-React:你可以使用 npm 或 yarn 安装这…...

技术洞察:Selenium WebDriver中Chrome, Edge, 和IE配置的关键区别
综述 webdriver.EdgeOptions(), webdriver.ChromeOptions(), 和 webdriver.IeOptions() 都是 Selenium WebDriver 的配置类,用于定制化启动各自浏览器的设置。它们分别对应 Microsoft Edge,Google Chrome,和 Internet Explorer 浏览器。 每…...

使用自定义OCR提升UIE-X检测效果:结合PaddleOCR和UIE模型进行文档信息提取
在实际应用中,识别文档中的特定信息对于许多任务至关重要,例如发票识别、表格信息提取等。然而,由于文档的多样性和复杂性,传统的光学字符识别(OCR)技术可能无法准确识别文档中的信息。为了解决这个问题&am…...

题目:写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度。
题目:写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度。 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog con…...

.net反射(Reflection)
文章目录 一.概念:二.反射的作用:三.代码案例:四.运行结果: 一.概念: .NET 反射(Reflection)是指在运行时动态地检查、访问和修改程序集中的类型、成员和对象的能力。通过反射,你可…...

P1278 单词游戏 简单搜索+玄学优化
单词游戏 传送门 题目描述 Io 和 Ao 在玩一个单词游戏。 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致。 游戏可以从任何一个单词开始。 任何单词禁止说两遍,游戏中只能使用给定词典中含有…...

软考 - 系统架构设计师 - 数据架构真题
问题 1: (相当于根据题目中提到的 4 点,说一下关系型数据库的缺点) (1).用户数量的剧增导致并发负载非常高,往往会达到每秒上万次读写请求。关系数据库应付每秒上万次的 SQL 查询还勉强可以,但是应付上万…...

Ubuntu22.04下opencv4.9.0环境的搭建
目录 1、更新系统包列表:2、安装依赖项:3、下载 OpenCV 源代码:4、编译和安装 OpenCV:5、配置环境变量:6、测试1、更新系统包列表: 在终端中执行以下命令,以确保系统包列表是最新的: sudo apt update2、安装依赖项: 安装构建 OpenCV 所需的依赖项: sudo apt inst…...

Flask如何在后端实时处理视频帧在前端展示
怎么样在前端->选择视频文件->点击上传视频后->后端实时分析上传的视频->在前端展示后端分析结果(视频,文本) ↓ 咱们先看整看整体代码,有个大概的印象。 Flask后端代码 cljc车流检测Demofrom pytz import timezon…...

04-15 周一 GitHub仓库CI服务器actions-runner和workflow yaml配置文档解析
04-15 周一 GitHub仓库CI服务器配置过程文档 时间版本修改人描述2024年4月15日10:35:52V0.1宋全恒新建文档2024年4月17日10:33:20v1.0宋全恒完成github actions CI的配置和工作流配置文件解读文档的撰写 简介 一些基础概念 前提知识 仓库介绍 地址镜像介绍https://github.…...

论文笔记:SmartPlay : A Benchmark for LLMs as Intelligent Agents
iclr 2024 reviewer评分 5688 引入了 SmartPlay,一种从 6 种不同游戏中提取的基准 衡量LLM作为智能体的能力 1 智能代理所需的能力 论文借鉴游戏设计的概念,确定了智能LLM代理的九项关键能力,并为每项能力确定了多个等级: 长文…...

搜维尔科技:【工业仿真】煤矿安全知识基础学习VR系统
产品概述 煤矿安全知识基础学习VR系统 系统内容: 煤矿安全知识基础学习VR系统内容包括:下井流程(正确乘坐罐笼、班前会、井下行走注意事项、工作服穿戴、入井检身及人员清点、下井前准备工作、提升运输安全);运煤流程…...

线程和进程的区别(面试)
线程和进程的区别 进程和线程的区别线程的优点 进程和线程的区别 1. 进程是系统进行资源分配和调度的一个独立单位,线程是程序执行的最小单位. 2. 进程有自己的内存地址空间,线程只独享指令流执行的必要资源,如寄存器和栈. 3. 由于同一进程的各线程共享内存和文件资源,可以不通…...

抓取电商产品数据的方法|电商平台商品详情数据|批量上架|商品搬家|电商封装API数据采集接口更高效安全的数据采集
大量级电商数据采集时使用电商API接口有以下优势: 1. 数据准确性:通过电商API接口获取数据,可以保证数据的准确性和实时性,避免了手动采集可能出现的错误和延迟。 2. 自动化采集:API接口可以实现自动化的数据获取和更…...

关联规则Apriori算法
1.前置知识 经典应用场景:购物车商品的关联规则。 符号表示: I代表项集,项是可能出现的值,例如购物车中能有尿布、啤酒、奶粉等,I{尿布、啤酒、奶粉},尿布是项 K代表I中包含的项的数目,上面的k3 事…...

书生·浦语大模型全链路开源体系-第4课
书生浦语大模型全链路开源体系-第4课 书生浦语大模型全链路开源体系-第4课相关资源XTuner 微调 LLMXTuner 微调小助手认知环境安装前期准备启动微调模型格式转换模型合并微调结果验证 将认知助手上传至OpenXLab将认知助手应用部署到OpenXLab使用XTuner微调多模态LLM前期准备启动…...

HTML优化SEO
在网站开发中,除了关注设计和用户体验,SEO(搜索引擎优化)也是提升网站流量和可见度的关键。合理的HTML结构和元素运用能够帮助搜索引擎更好地理解页面内容,从而提高搜索排名。以下是一些基于HTML的SEO优化技巧…...

RabbitMQ-交换机
文章目录 交换机fanoutDirecttopicHeadersRPC 交换机 **交换机 **是消息队列中的一个组件,其作用类似于网络路由器。它负责将我们发送的消息转发到相应的目标,就像快递站将快递发送到对应的站点,或者网络路由器将网络请求转发到相应的服务器…...

mapreduce中的MapTask工作机制(Hadoop)
MapTask工作机制 MapReduce中的Map任务是整个计算过程的第一阶段,其主要工作是将输入数据分片并进行处理,生成中间键值对,为后续的Shuffle和Sort阶段做准备。 1. 输入数据的划分: 输入数据通常存储在分布式文件系统(…...

景区文旅剧本杀小程序亲子公园寻宝闯关系统开发搭建
要开发景区文旅剧本杀小程序亲子公园寻宝闯关系统,您需要考虑以下步骤: 1. 设计游戏场景和规则:根据亲子公园的主题和特点,设计适合亲子游玩的游戏场景和规则。您需要考虑游戏的安全性、趣味性和互动性,确保孩子们能够…...

性能优化---webpack优化
1、如何提高webpack打包速度 a、优化Loader--影响Loader打包速度的首要元素是Babel,Babel 会将代码转为字符串生成 AST,然后对 AST 继续进行转变最后再生成新的代码,项目越大,转换代码越多,效率就越低。先优化 Loader …...

YOLOv9改进策略 | 损失函数篇 | EIoU、SIoU、WIoU、DIoU、FocusIoU等二十余种损失函数
一、本文介绍 这篇文章介绍了YOLOv9的重大改进,特别是在损失函数方面的创新。它不仅包括了多种IoU损失函数的改进和变体,如SIoU、WIoU、GIoU、DIoU、EIOU、CIoU,还融合了“Focus”思想,创造了一系列新的损失函数。这些组合形式的…...

贪心算法-跳跃游戏
给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例 1: 输…...

sql知识总结二
一.报错注入 1.什么是报错注入? 这是一种页面响应形式,响应过程如下: 用户在前台页面输入检索内容----->后台将前台输入的检索内容无加区别的拼接成sql语句,送给数据库执行------>数据库将执行的结果返回给后台ÿ…...

VSCode和CMake实现C/C++开发
VSCode和CMake实现Ubuntu下C/C++开发总结 目录 0.简介1.Linux系统介绍2.开发环境搭建2.1 编译器,调试器安装2.2 CMake安装3.GCC编译器3.1 编译过程3.2 g++重要编译参数4.g++编译实战4.0 编译前4.1 直接编译4.2 生成库文件并编译4.3 编译后4.3.1 编译完成后的目录结构4.3.2 运行…...

【机器学习300问】74、如何理解深度学习中L2正则化技术?
深度学习过程中,若模型出现了过拟合问题体现为高方差。有两种解决方法: 增加训练样本的数量采用正则化技术 增加训练样本的数量是一种非常可靠的方法,但有时候你没办法获得足够多的训练数据或者获取数据的成本很高,这时候正则化技…...

C语言程序设计每日一练(4)
完全平方数 首先,我们需要明确什么是完全平方数。完全平方数是指一个整数,它可以表示为另一个整数的平方。例如,1、4、9、16等都是完全平方数,因为它们分别是1、2、3、4的平方。 现在,让我们回到这个问题。我们知道这…...