C语言进阶指南(14)(部分字符串库函数及其模拟实现)

欢迎来到博主的专栏——C语言进阶指南
博主id:reverie_ly

文章目录

    • 1、strlen()——字符串长度计算函数
      • 自定义strlen函数的实现
    • 2、strcpy——字符串拷贝函数
      • strcpy的模拟实现
    • 3.strcat——字符串追加函数
      • strcat的模拟实现
    • 4、strcmp——字符串比较函数
      • strcmp的模拟实现
    • 加了限定条件的字符串操作函数
    • 更多的库函数

C语言标准定义了一系列有关字符串操作的函数,编译器会根据标准中的定义实现这些函数, 并将这些字符串函数定义在头文件<string.h>中
如果想要使用这些字符串函数,需要在包含这个头文件

#include<string.h>

1、strlen()——字符串长度计算函数

在这里插入图片描述

该函数的计算方式是从传进函数的地址值的第一个元素开始,直到结束标志‘\0’之间的所有元素的长度作为函数的返回值。

字符串必须有结束标志‘\0’,否则返回值将是一个随机值(strlen函数继续在内存中寻找‘\0’,返回值是从目标地址到‘\0’的元素长度)。

函数的返回值是size_t.由定义可知,size_t类型实质上是unsigned int类型。

在这里插入图片描述
以字符串“hello,world”为例。

char ch[12] = { "hello,world" };

如果将首元素的地址传入strlen函数,返回值是从‘h’—‘\0’之间的元素个数,(不计入‘\0’)

strlen(ch);//返回值为11

在这里插入图片描述
也可以传递字符串的其他元素,此时函数的返回值是以传入的元素为起始,一直到‘\0’之间的字符个数

strlen(&ch[4]);//将字符串中的第五个元素的地址传入函数中

在这里插入图片描述
此时strlen函数的返回值为7

自定义strlen函数的实现

前面已经知道了strlen函数的原理
(1)函数原型的参数是字符串的地址
(2)函数的返回值是size_t类型(size_t定义在<stdio.h>中)
(3)函数从传入的地址为起始位置,一直计算到’\0’之间的字符个数

我们可以根据(1)(2)设计出函数原型

#include<stdio.h>
size_t my_Strlen(const char*str);

为了实现(3),我们将指针从起始位置逐个解引用,判断是否为‘\0’,不是‘\0’就给计数增加1.

size_t my_strlen(const char* pstr)
{size_t count = 0;while (*pstr != 0) {count++;pstr++;}return count;
}

润色一下可以变成

size_t my_strlen(const char* pstr)
{size_t count = 0;while (*pstr++&&++count);//这里是利用了&&的的特性,如果大家感兴趣//可以去看看博主那篇关于逻辑运算符的文章哦~return count;
}

2、strcpy——字符串拷贝函数

在这里插入图片描述
将source地址的字符串(从开始地址到结束标志)拷贝到destination字符串中去。
1)目的字符串必须能被修改。
2)目的字符串的容量需要大于原字符串。
3)原字符串需要有结束标志‘\0’

char str1[20]="reverie";
char str2[20]="hello";
strcpy(str1,str2);

strcpy会将str2中的字符串(从首元素到‘\0’之间的所有字符,包括‘\0’)拷贝到str1中。
在这里插入图片描述

strcpy的模拟实现

返回类型是目的字符串的地址,参数是两个字符型指针,源字符串不更改,使用const固定变量。

char* my_strcpy(char*destination,const char*source);

一直到打印完源字符串(从起始地址到结束标志)

实现这个功能可以将source指向的元素传到destination指针指向的元素中,接着两个指针继续拷贝后边的字符,直到source拷贝完‘\0’

char* my_strcpy(char* destination, char* source)
{char* ret = destination;//保存起始地址while (source != '\0'){*destination = *source;destination++;source++;}*destnation=*source;return ret;//拷贝完成后返回起始地址
}

跳出循环后需要加上一句*destination=*source,这是因为循环结束的条件是*source!=‘\0’(如果不限定的话会死循环),但是根据上面实现的结果来看,source字符串的第一个’\0’是要被读入进去的,所以在循环结束后需要加上*destination=*source;
(而且字符串是一个从起始字符一直到第一个字符串结束符号‘\0’组成的字符集合,不录入\0是不能算作拷贝一个字符串的)

稍微润色一下变成

char* my_strcpy(char* destination, char* source)
{char* ret = destination;while (*source++ = *source++);return ret;
}

3.strcat——字符串追加函数

在这里插入图片描述

将source字符串的所有字符追加到destination字符串,具体实现是将source字符串的首元素开始依次附加到destination字符串的第一个结束标志‘\0’。返回值为追加后的destination字符串的地址

char str1[12]="hello";
char str2[]=",world";
strcat(str1,str2);

在这里插入图片描述

1)目标字符串的空间需要足够大(能够容纳追加后的字符个数)
2)源字符串需要有结束标志
3)源字符串不能被修改(所以不能自己追加自己)。
4)目标字符串能被修改

strcat的模拟实现

(1)源字符串不能被修改,用const修饰指针。
(2)函数的返回值是指向目的字符串的指针。
(3)将原字符串追加到目的字符串。从目的字符串的第一个字符串结束标志开始追加

由(1)(2)可以得出strcat的函数原型

char* my_strcat(char*destnation,const char*source);

实现(3)的方法是:
先将指针指向目的字符串的第一个字符串结束标志处。
将源字符串的元素依次拷贝到目的字符串的指针处的元素。

char* my_strcat(char* destination, const char* source)
{char* ret = destination;while (*destination != '\0')destination++;while (*source != '\0'){*destination = *source;destination++;source++;} *destination=*source;return ret;
}

稍微润色一下变成

char* my_strcat(char* destination, const char* source)
{char* ret = destination;while (*destination)destination++;while (*destination++ = *source++);return ret;
}

4、strcmp——字符串比较函数

在这里插入图片描述

将字符串中的每个字符依次对比大小(ASCII码值),若大于则返回1,小于则返回-1,若相同,则继续对比双方字符串下一个元素,直到某一方出现不同的值或出现字符串结束标志‘\0’,若自始至终对比的双方字符串中的每一个元素都相等,则返回值为0.

不同的编程环境下返回值的结果不同,在vs中返回值为1,0,-1,而gcc中返回值为判定元素(被比较的字符)之间ASCII码值的差值。

在这里插入图片描述

以上例为例,str1与str2进行字符串比较时,‘w’与‘w’相等,继续比较下一个。‘o’与‘o’相等,继续比较下一个。‘r’与‘r’相等,继续比较下一个。‘l’与‘d’比较,不相等,由于‘l’的ASCII码值比‘d’大,函数的返回值大于0.

在这里插入图片描述

‘w’和‘w’相等,比较下一个,以此类推,当某一个字符串比较到‘\0’时,停止比较,此时判断双方对应比较的字符是否都是‘\0’,如果一致,则判断这两个字符串相等。

strcmp的模拟实现

(1)函数的返回值是有符号型(有负数,有正数)
(2)对比过程中不对字符串的数据进行修改,可以用const修饰函数参数。
(3)将字符串的元素依次比较大小,满足上面的规则
根据(1)(2),可以确定函数原型

char* my_strcmp(const char*str1,const char*str2)
{
char* my_strcmp(const char* str1, const char* str2)
{while (*str1 == *str2){if (*str1 == '\0')return 0;str1++;str2++;}if (*str1 > *str2){return 1;}elsereturn 0;
}
}

如果想要模拟的是gcc编译器的strcmp实现效果的话,模拟实现应该是。

char* my_strcmp(const char* str1, const char* str2)
{while (*str1 == *str2){if (!str1)return 0;str1++, str2++;}return *str1 - *str2;
}

加了限定条件的字符串操作函数

strcpy,strcmp,strcat的限定条件都是字符串结束标志‘\0’。为了达到更灵活的效果(比如只拷贝字符串的前几个字符,而不用一直拷贝到‘\0’)。C语言推出了加了限定条件的字符串操作函数:strncpy,strncmp,strncat。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
依次对比strcpy,strcat,strcmp的声明我们发现其多出一个size_t的参数count。这是用来计算参与函数的字符串中的限定元素个数。
在这里插入图片描述

由strncpy的模拟实现我们可以知道syrncpy的特点是1)将源字符串的前n个字符传递到目的字符串,若原字符串的字符数小于n,则其余字符(n-已修改字符)改为‘\0。

在这里插入图片描述

strcmp一直对比到某一方出现‘\0’或不同,strncmp是依次对比前n个字符是否相等。但是当strncmp中的前n个字符串中存在‘\0’也会停止对比。

这些函数无非就是在原有的函数原型上加上了一个限定条件count,这个count是限定了需要参与这个函数的字符的最大个数。

更多的库函数

cplusplus网站,这里有C语言所有库的库函数的讲解

也可以使用msdn软件来查看这些库函数的使用方法以及函数的返回类型。
在这里插入图片描述
(可以私信博主来获取msdn软件哦~)

也可以继续关注博主,博主会带来常用库函数的讲解哦(额)

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

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

相关文章

【计算机毕业设计】nodejs+vue音乐播放器系统 微信小程序83g3s

本系统的设计与实现共包含12个表:分别是配置文件信息表&#xff0c;音乐列表评论表信息表&#xff0c;音乐论坛信息表&#xff0c;歌手介绍信息表&#xff0c;音乐资讯信息表&#xff0c;收藏表信息表&#xff0c;token表信息表&#xff0c;用户表信息表&#xff0c;音乐类型信…

selenium使用记录

本文记录python环境下使用selenium的一些步骤 Step1&#xff1a;安装并配置驱动 pip install selenium # 使用pip在对应python中安装selenium包为了让selenium能调用指定的浏览器&#xff0c;需要下载对应浏览器的驱动程序&#xff08;这里以edge为例子&#xff09; #Firefo…

DockerCompose修改某个服务的配置(添加或编辑端口号映射)后如何重启单个服务使其生效

场景 docker-compose入门以及部署SpringBootVueRedisMysql(前后端分离项目)以若依前后端分离版为例&#xff1a; docker-compose入门以及部署SpringBootVueRedisMysql(前后端分离项目)以若依前后端分离版为例_docker-compose部署java mysql redis-CSDN博客 上面讲了docker c…

centos7-docker安装与使用

文章目录 一、docker简介1.1docker应用场景1.2docker的优点1.2.1快速&#xff0c;一致地交付应用程序1.2.2响应式部署和扩展1.2.3在同一硬件上运行更多工作负载 1.2docker的架构 二、docker的安装2.1新系统的环境搭建2.1.1更换yum源 2.2安装docker与卸载2.2.1yum安装docker2.2.…

SpringBoot——Swagger2 接口规范

优质博文&#xff1a;IT-BLOG-CN 如今&#xff0c;REST和微服务已经有了很大的发展势头。但是&#xff0c;REST规范中并没有提供一种规范来编写我们的对外REST接口API文档。每个人都在用自己的方式记录api文档&#xff0c;因此没有一种标准规范能够让我们很容易的理解和使用该…

【数据结构】八大排序 (三)

目录 前言&#xff1a; 快速排序 快速排序非递归实现 快速排序特性总结 归并排序 归并排序的代码实现 归并排序的特性总结 计数排序 计数排序的代码实现 计数排序的特性总结 前言&#xff1a; 前文快速排序采用了递归实现&#xff0c;而递归会开辟函数栈帧&#xff0…

谨慎Apache-Zookeeper-3.5.5以后在CentOS7.X安装的坑

目录 前言 一、现场还原 二、问题诊断 三、问题原因 总结 前言 最近由于项目需要&#xff0c;在服务器上需要搭建Hbase完全分布式集群环境。开发环境&#xff0c;采用的是最小节点的方式进行搭建&#xff08;即3个节点的模式&#xff09;。资源环境列表如下&#xff1a; 序号…

[Docker]十二.Docker consul集群搭建、微服务部署,Consul集群+Swarm集群部署微服务实战

一.Docker consul集群搭建 Consul 是 Go 语言写的开源的服务发现软件&#xff0c; Consul 具有 服务发现、健康检查、 服务治理、微服务熔断处理 等功能,在微服务中讲过如何搭建consul集群&#xff0c;接下来看看在 Dokcer 中如何去创建搭建consul 集群 1.linux上面部署consul集…

kafka C++实现生产者

文章目录 1 Kafka 生产者的逻辑2 Kafka 的C API2.1 RdKafka::Conf2.2 RdKafka::Message2.3 RdKafka::DeliveryReportCb2.4 RdKafka::Event2.5 RdKafka::EventCb2.6 RdKafka::PartitionerCb2.7 RdKafka::Topic2.8 RdKafka::Producer&#xff08;核心&#xff09; 3 Kafka 生产者…

系列十八、Spring bean线程安全问题

一、概述 我们知道Spring中的bean&#xff0c;默认情况下是单例的&#xff0c;那么Spring中的bean是线程安全的吗&#xff1f;这个需要分情况考虑&#xff0c;bean中是否存在成员变量&#xff1f;bean中的成员变量是怎么处理的&#xff1f;...&#xff0c;针对bean的状态会有不…

商品橱窗和抖音小店有什么区别?新手应该选择哪一个?

我是电商珠珠 在抖音小店内&#xff0c;有两种经营方式&#xff0c;一种是商品橱窗&#xff0c;还有一种是抖音小店。 很多人会将他们混之一谈&#xff0c;说开抖店需要粉丝&#xff0c;商品橱窗不用。 事实真的是这样吗&#xff1f; 接下来&#xff0c;我就来给大家讲讲二…

优化机器学习:解析数据归一化的重要性与应用

在机器学习中&#xff0c;数据归一化是一种数据预处理的技术&#xff0c;旨在将数据转换为相似的范围或标准化的分布。这样做的主要目的是消除不同特征之间的量纲差异或数值范围差异&#xff0c;以确保模型在训练时更稳定、更有效地学习特征之间的关系。 通常&#xff0c;机器…

【数据挖掘】国科大刘莹老师数据挖掘课程作业 —— 第三次作业

Written Part 1. 基于表 1 1 1 回答下列问题&#xff08;min_sup40%, min_conf75%&#xff09;&#xff1a; Transaction IDItems Bought0001{a, d, e}0024{a, b, c, e}0012{a, b, d, e}0031{a, c, d, e}0015{b, c, e}0022{b, d, e}0029{c, d}0040{a, b, c}0033{a, d, e}0038…

Django报错:RuntimeError at /home/ 解决办法

错误提示&#xff1a; RuntimeError at /home/ Model class django.contrib.contenttypes.models.ContentType doesnt declare an explicit app_label and isnt in an application in INSTALLED_APPS. 原因剖析&#xff1a; 博主在使用pycharm创建Django项目的时候&#xff0…

Jmeter和Testlink自动化测试框架研究与实施

摘 要 目前基于Jmeter的接口自动化测试框架&#xff0c;大多只实现脚本维护和自动调度&#xff0c;无法与Testlink进行互通&#xff0c;实现测试方案与自动化实施流程连接&#xff0c;本文基于Testlink、Jmeter、Jenkins实现&#xff1a;通过Testlink统一维护接口自动化测试用…

渲染到纹理:原理及WebGL实现

这篇文章是WebGL系列的延续。 第一个是从基础知识开始的&#xff0c;上一个是向纹理提供数据。 如果你还没有阅读过这些内容&#xff0c;请先查看它们。 NSDT在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - …

webpack external 详解

作用&#xff1a;打包时将依赖独立出来&#xff0c;在运行时&#xff08;runtime&#xff09;再从外部获取这些扩展依赖&#xff0c;目的时解决打包文件过大的问题。 使用方法&#xff1a; 附上代码块 config.set(externals, {vue: Vue,vue-router: VueRouter,axios: axios,an…

Spark on yarn 模式的安装与部署

任务描述 本关任务&#xff1a; Spark on YARN 模式的安装与部署。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; Spark 部署模式的种类&#xff1b;Spark on YARN 模式的安装。 Spark 部署模式 Spark 部署模式主要分为以下几种&#xff0c;Spark Stand…

Compose入门

​ 本篇文章主要是为了对Compose有一个初步了解。知道Compose是做什么的&#xff0c;用Compose能干什么&#xff0c;在目前的各种UI框架下面有些优势&#xff0c;参考Google官网的解释加上一些自己的理解生成的一篇文章。本人也是Compose初学者&#xff0c;通过每一步学习遇到哪…

系统频繁崩溃,如何考虑系统的稳定性和可扩展性?

最近网传互联网应用信息系统频繁崩溃&#xff0c;语雀崩完淘宝崩&#xff0c;淘宝崩完滴滴崩&#xff0c;随着业务的发展和技术的进步&#xff0c;对于信息系统的要求也越来越高。信息应用系统为了满足不断增长的用户和业务需求&#xff0c;提高系统的稳定性和扩展性至关重要。…