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;
	}
	else
		return 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软件哦~)

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

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

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

相关文章

vue2+element-ui npm run build打包后,在服务器打开报错

报错 页面的图标也显示不出来&#xff0c;如下 解决&#xff1a; 在build->utils.js文件里面加上publicPath: ../../&#xff0c;再打包发布一下就可以了 // Extract CSS when that option is specified// (which is the case during production build)if (options.extrac…

LabVIEW当鼠标悬停在图形曲线上时显示坐标

LabVIEW当鼠标悬停在图形曲线上时显示坐标 在波形图上显示波形数据后&#xff0c;当鼠标放在波形图的曲线上时&#xff0c;如何自动显示对应点的坐标&#xff1f; 1. 创建事件结构&#xff0c;选择“波形图”作为“事件源”&#xff0c;选择“鼠标移动”作为“事件”&a…

MySQL之redo log

聊聊REDO LOG 为什么需要redolog&#xff1f; 那redolog主要是为了保证数据的持久化&#xff0c;我们知道innodb存储引擎中数据是以页为单位进行存储&#xff0c;每一个页中有很多行记录来存储数据&#xff0c;我们的数据最终是要持久化到硬盘中&#xff0c;那如果我们每进行…

为什么 SQL 日志文件很大,我应该如何处理?

SQL Server 日志文件是记录所有数据库事务和修改的事务日志文件。在 SQL 术语中&#xff0c;此日志文件记录对数据库执行的所有 INSERT、UPDATE 和 DELETE 查询操作。 如果数据库处于联机状态或处于恢复状态时日志已满&#xff0c;则 SQL Server 通常会发出 9002 错误。在这种…

windows系统用nginx部署web应用

要在Windows系统上使用Nginx进行本地部署和运行Web应用程序&#xff0c;可以按照以下步骤进行操作&#xff1a; 1.首先下载nginx&#xff0c;需要去nginx官网&#xff1a; nginx: download 下载最新版本的&#xff1a; 2.解压缩Nginx&#xff1a;找个磁盘位置&#xff0c;新…

C++ AVL 树

AVL树的概念 当数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;此时二叉搜索树的搜索效率低下 解决方法&#xff1a;AVL树&#xff08;降低树的高度&#xff0c;从而减少平均搜索长度) 一棵AVL树或者是空树&#xff0c;或者是具有以下性质的二叉搜索树&#xff1…

1.自动化运维工具Ansible的安装

1.物料准备 四台服务器&#xff0c;其中一个是主控机&#xff0c;三个为host 2.安装 在主控机上安装ansible 2.1 设置EPEL仓库 Ansible仓库默认不在yum仓库中&#xff0c;因此我们需要使用下面的命令启用epel仓库。 yum install epel-release -y2.2 执行安装命令 yum i…

temu的产品发布后在哪里显示

temu是一款备受瞩目的产品&#xff0c;其发布后引起了广泛的关注。但是&#xff0c;很多人对于temu产品发布后在哪里显示存在疑惑。本文将深入探讨temu产品的展示方式和关键特点&#xff0c;帮助读者更好地了解temu产品在发布后的展示位置。 先给大家推荐一款拼多多/temu运营工…

贝锐向日葵与华为达成合作,启动鸿蒙原生应用开发

2023年11月24日&#xff0c;贝锐与华为携手举办鸿蒙原生应用开发启动仪式。贝锐创始人之一兼首席技术官张小峰先生、贝锐事业部总经理张海英女士共同出席了此次活动&#xff0c;并达成重大合作。贝锐旗下国民级远程控制品牌贝锐向日葵将以原生方式适配鸿蒙系统&#xff0c;成为…

串口理解小结(UART)

串口作为单片机的必备外设&#xff0c;主要用于单片机与其它模块的信息通讯、程序烧录和升级作用。 UART全称为通用异步收发器。 可分为&#xff1a; 一、串行和并行 串行指数据位只能一位一位地发送 并行之多个数据位同时发送 二、同步和异步 同步和异步是相当于时钟而…

AcWing 3555:二叉树(北京大学考研机试题)→公共父结点

【题目来源】https://www.acwing.com/problem/content/description/3435/【题目描述】 如下图所示&#xff0c;由正整数 1, 2, 3, … 组成了一棵无限大的&#xff08;满&#xff09;二叉树。 1/ \2 3/ \ / \4 5 6 7 /\ /\ /\ /\ ... ... 从任意一个结点到根结点&…

25. 深度学习进阶 - 权重初始化,梯度消失和梯度爆炸

文章目录 权重初始化梯度消失与梯度爆炸 Hi&#xff0c;你好。我是茶桁。 咱们这节课会讲到权重初始化、梯度消失和梯度爆炸。咱们先来看看权重初始化的内容。 权重初始化 机器学习在我们使用的过程中的初始值非常的重要。就比如最简单的wxb&#xff0c;现在要拟合成一个yha…

TZOJ 1373 求多项式的和

答案&#xff1a; #include <stdio.h> int main() {int m 0;scanf("%d", &m); // 读取测试实例的个数 while (m--) //循环m次{int n 0, i 0;scanf("%d", &n); // 读取求和项数n double sum 0.0;for (i 1; i < n; i) //分…

JenKins快速安装与使用

一、JenKins 0.准备&#xff0c;配置好环境 1&#xff09;Git&#xff08;yum安装&#xff09; 2&#xff09;JDK&#xff08;自行下载&#xff09; 3&#xff09;Jenkins&#xff08;自行下载&#xff09; 1.下载安装包 进官网&#xff0c;点Download下方即可下载。要下…

linux之下安装 nacos

1 下载地址 也可使用在线下载wget https://github.com/alibaba/nacos/releases/download/1.4.6/nacos-server-1.4.6.tar.gzTags alibaba/nacos GitHuban easy-to-use dynamic service discovery, configuration and service management platform for building cloud nativ…

一次Apollo Client升级导致的生产404 Not Found问题排查记录

概述 本文记录一次升级Apollo Client组件到1.7.0后遇到的重大生产事故。只想看结论的&#xff0c;可直接快进到文末。实际上&#xff0c;第一句话就是一个结论。 另&#xff0c;本文行文思路事后看起来可行略显思路清晰&#xff0c;实际上排查生产问题时如无头苍蝇&#xff0…

使用STM32微控制器实现烟雾传感器的接口和数据处理

烟雾传感器是常见的安全检测装置&#xff0c;通过检测空气中的烟雾浓度来提醒用户有潜在的火灾风险。本文将介绍如何使用STM32微控制器来实现烟雾传感器的接口和数据处理。包括硬件连接、采集模拟信号、数字信号处理和报警策略等方面。同时&#xff0c;给出相应的代码示例。 一…

【Android知识笔记】架构专题(一)

什么是 MVC 其实我们日常开发中的Activity,Fragment和XML界面就相当于是一个MVC的架构模式,但往往Activity中需要处理绑定UI,用户交互,以及数据处理。 这种开发方式的缺点就是业务量复杂的时候一个Activity过于臃肿。但是页面结构不复杂的情况下使用这种方式就会显得很简…

基于Java SSM框架实现KTV点歌系统项目【项目源码+论文说明】

基于java的SSM框架实现KTV点歌系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个KTV点歌系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述KTV点歌系…

Linux基础项目开发1:量产工具——输入系统(三)

前言&#xff1a; 前面我们已经实现了显示系统&#xff0c;现在我们来实现输入系统&#xff0c;与显示系统类似&#xff0c;下面让我们一起来对输入系统进行学习搭建吧 目录 一、数据结构抽象 1. 数据本身 2. 设备本身&#xff1a; 3. input_manager.h 二、触摸屏编程 to…