【C语言】长篇详解,字符系列篇2-----受长度限制的字符串函数,字符串函数的使用和模拟实现【图文详解】

news2024/11/25 7:50:59

欢迎来CILMY23的博客喔,本期系列为【【C语言】长篇详解,字符系列篇2-----“混杂”的字符串函数,字符串函数的使用和模拟实现【图文详解】,图文讲解各种字符串函数,带大家更深刻理解C语言中各种字符串函数的应用,感谢观看,支持的可以给个赞哇。

前言

上一篇说到,在C语言中,我们常常碰见各种字符,也需要对字符进行处理,那C语言提供了一系列的库函数,来帮助我们处理各种情况。字符函数有字符串函数,字符分类函数,还有字符转换函数……本期我们将深入了解各种字符串函数(strcpy,strcat,strcmp,strncpy,strncat)

目录

 一、strcat函数

二、strcmp函数

三、strncpy函数

四、strncat函数

五、strncmp函数


一、strcat函数

 该函数可以在cplusplus网站查询到,strcat - C++ Reference (cplusplus.com)

 函数原型如下:

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

函数介绍如下: 

 返回值和使用案例:

 

先简单了解一下strcat函数吧,strcat函数它的功能是Concatenate strings,意思是连接字符串。concatenate它的意思如下

了解完这个功能后,我们大致也清楚了,strcat的作用就是拼接字符串啦,那函数的使用如下:

#include<stdio.h>
#include<string.h>

int main()
{
	char str1[50] = "hello ";
	char str2[] = "CILMY23";
	
	strcat(str1, str2);
	printf("%s ", str1);

	return 0;
}

我们可以把第二个字符串拼接到第一个字符串末尾,这样就concatenate起来了。 

结果如下:

总结:

1.strcat的功能是拼接字符串,目标空间要有'\0',并且源字符串要有'\0'。

2.strcat的使用需要包括头文件string.h

3.strcat的返回地址是destnation的地址

4.目标空间要足够大,并且可以修改

   strcat的模拟实现 

我们看以下这段最简单粗暴的代码,思路是比较直接的,先遍历所需要追加的字符串空间,找到'\0'的位置,然后从'\0'的位置开始用新的字符串覆盖,最后添加'\0'就行。 

char* my_strcat(char * dest, const char* src)
{
	assert(dest);
	assert(src);

	char* ret = dest;

	while (*dest != '\0')
	{
		dest++;
	}

	while (*src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = '\0';

	return ret;
}

 逻辑图如下所示:

代码还可以进行优化,那如何优化呢?实际上我们可以发现,后面一段有点类似于把str2给它复制到str1当中,这不就是我们字符篇1学到的strcpy嘛,(不懂可以跳转连接http://t.csdnimg.cn/CvvpI) 

所以第二步的优化就可以写成这样

char* my_strcat(char * dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;

	while (*dest != '\0')
	{
		dest++;
	}

	strcpy(dest, src);

	return ret;
}0

二、strcmp函数

该函数可以在cplusplus查找到:strcmp - C++ Reference (cplusplus.com)

函数原型如下:

int strcmp ( const char * str1, const char * str2 );

 函数介绍如下:

函数返回值和使用案例:

简单了解一下strcmp函数吧,它的功能是Compare two strings,Compares the C string str1 to the C string str2.,比较两个字符串,它的返回值是如果是第一个字符串小于第二个字符串就返回一个小于0的值,如果第一个字符串和第二个字符串相等就返回0,如果第一个字符串大于第二个字符串,就返回一个大于0的值。

strcmp的使用:

#include<stdio.h>
#include<string.h>

int main()
{
	char str1[] = "hello ";
	char str2[] = "CILMY23";
	
	int ret = strcmp(str1, str2);
	printf("%d ", ret);

	return 0;
}

 解析:因为h是在ASCII码比C大的,所以返回了1

 总结:

1.strcmp实际是按照两个字符串对应位置一个个进行比较的,而且是按照字典序(ASCII码值)比较的

2.strcmp的使用需要包括头文件string.h

3.返回值:

◦    第⼀个字符串大于第二个字符串,则返回大于0的数字
◦    第⼀个字符串等于第二个字符串,则返回0
◦    第⼀个字符串小于第二个字符串,则返回小于0的数字

strcmp的模拟实现

字符串相对比的三种情况,相等,大于,和小于,如果字符串两个相对比是相等的话,那指针就需要往后走,它们结束的标志是‘\0’,如果走到了这个‘\0’,那说明两个字符串是相等的,出了循环后,那说明二者不相等,就进行判断,根据判断后写返回值。

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);

	while (*str1 == *str2)
	{
		if (*str1  == '\0')
			return 0;
		str1++;
		str2++;
	}

	if (*str1 > *str2)
		return 1;
	else
		return -1;
}

 当然后面的返回值也可以用指针解引用后相减得到的值,不固定,主要是灵活使用,

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);

	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}

	return *str1 - *str2;
}

这是当str1和str2相等的情况下:注意图片中红色的是字符数组,而黑色的str1和str2是指针。 

当二者不相等的时候: 

 

就会马上比对出结果。

我写的几个测试用例也给大家放这了:

int main()
{
	char str1[] = "CILMY23";
	char str2[] = "CILMY23";
	char str3[] = "";
	char str4[] = "helllo ";

	int ret = my_strcmp(str1, str2);
	printf("%d \n", ret);
	ret = my_strcmp(str3, str2);
	printf("%d \n", ret);
	ret = my_strcmp(str4, str2);
	printf("%d \n", ret);
	ret = my_strcmp(str3, str4);
	printf("%d \n", ret);

	return 0;
}

三、strncpy函数

如果讲完以上三个函数相信大家对其都有个大致的了解了,那以上三个(strcpy,strcat,strcmp)都是长度不受限制的字符串函数,它们只会一股脑的走到尾巴,我想要只复制几个字符,链接几个字符,比较几个字符,这时候库函数就给我们提供了三个加n的字符串函数,它们分别是strncpy,strncat,strncmp函数,有了这三个函数,我们就可以指定几个字符来进行相对应的操作。 它们都在相对于的原型基础上,增加了一个形参size_t num。

首先我们先来认识一下strncpy这个函数,strncpy - C++ Reference (cplusplus.com)

函数原型如下:

char * strncpy ( char * destination, const char * source, size_t num );

函数介绍如下: 

  函数返回值和使用案例如下:

 函数的使用呢,重点还是如果字符串不够怎么办?

#include<stdio.h>
#include<string.h>

int main()
{
	char str1[] = "CILMY23";
	char str2[50];

	strncpy(str2, str1, 9);

	printf("%s ", str2);

	return 0;
}

 我们知道九个复制是远超过str1的数量的,那内存里复制了什么过去呢?

通过下图我们可以看到在23后面放的是'\0',所以如果num超过源字符串之后,就会不停的拷贝'\0',直到复制结束。

总结:

•    拷贝num个字符从源字符串到目标空间。
•    如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。 

strncpy的模拟实现

char* my_strncpy(char* dest, const char* src, size_t num)
{
	char* ret = dest;
	assert(dest && src);

	while (*dest++ = *src++)
	{
		if (num == 1)
		{
			*dest = '\0';
			break;
		}
		num--;
	}

	while (num > 1)
	{
		*dest++ = '\0';
		num--;
	}
	
	return ret;
}

 上述代码是我第一种思路,根据原先代码改造的,其实跟原来差不多,只是这里多了个num操作,因为我的循环它会先赋值,后判断,所以在我已经把C赋值给str2空间的时候,num还是3,I赋值给完str2的时候,num--后才是2,我L又复制完了,num--后1了,这个时候我已经操作三次赋值了,但是num并不为0,所以此刻等于1的时候要将0赋值进去,然后跳出循环再进行赋值‘\0’操作。

我的第二种思路就是通过判断num,num如果为0就结束了。因为源字符串的结束标志是'\0',那不是'\0',那我就是在复制'\0'之前的字符。那我就先赋值,把src的内容复制进去,因为复制进去后,dest和src都指向下一个位置了,这时候我把*dest直接用‘\0’覆盖,如果num--后为0,这个时候我就刚好只拷贝一个字符,那如果num是大于源字符串函数的,那么在复制完源字符串后,*src就停留在‘\0’ 了,这时候只要不断给dest添加'\0'就完事了。

char* my_strncpy(char* dest, const char* src, size_t num)
{
	char* ret = dest;
	assert(dest && src);

	while (num--)
	{
		if (*src != '\0')
		{
			*dest++ = *src++;
		}
		*dest = '\0';
	}

	return ret;
}

测试部分:这里我是把原先的Cplusplus网站中的案例扣过来用了结果是一样的

int main()
{
	char str1[] = "To be or not to be";
	char str2[40];
	char str3[40];

	/* copy to sized buffer (overflow safe): */
	my_strncpy(str2, str1, sizeof(str2));

	/* partial copy (only 5 chars): */
	my_strncpy(str3, str2, 5);
	str3[5] = '\0';   /* null character manually added */

	puts(str1);
	puts(str2);
	puts(str3);

	return 0;
}

 我的逻辑可能会比较复杂,如果你有其他的方法欢迎在评论区探讨。

四、strncat函数

函数原型如下:strncat - C++ Reference (cplusplus.com)

char * strncat ( char * destination, const char * source, size_t num );

函数介绍如下:

 函数返回值和使用案例如下:

 strncat的模拟实现

首先我仍然按照之前strncpy的第二种思路进行实现,我们需要先找到需要拼接的dest的尾巴'\0',然后从'\0'开始拼接。拼接的数量还是由num来决定。

char* my_strncat(char* dest, const char* src, size_t num)
{
	char* ret = dest;
	assert(dest && src);
	//找尾
	while (*dest != '\0')
	{
		dest++;
	}

	while (num--)
	{
		if (*src != '\0')
		{
			*dest++ = *src++;
		}

		*dest = '\0';
	}

	return ret;
}

 测试用例以及结果如下:

int main()
{
	char str1[20];
	char str2[20];
	strcpy(str1, "To be ");
	strcpy(str2, "or not to be");
	
	my_strncat(str1, str2, 6);
	puts(str1);
	return 0;
}

 五、strncmp函数

 strncmp:strncmp - C++ Reference (cplusplus.com)

函数原型如下:

int strncmp ( const char * str1, const char * str2, size_t num );

函数介绍如下:

函数返回值和使用案例如下: 

 strncmp的模拟实现

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);
	while (num--)
	{
		if(*str1 == *str2)
		{
			if (*str1 == '\0')
				return 0;
			str1++;
			str2++;
		}
		else
		return *str1 - *str2;
	}
}

该思路来自之前写过的,我们只需要将不等于的返回即可 

感谢各位同伴的支持,本期字符函数篇2就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。  

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小型医院医疗设备管理系统|基于springboot小型医院医疗设备管理系统设计与实现(源码+数据库+文档)

小型医院医疗设备管理系统目录 目录 基于springboot小型医院医疗设备管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、职员信息管理 2、设备信息管理 3、库房信息管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、…

【性能测试入门必看】性能测试理论知识

一、性能测试理论知识 1、常用的七种性能测试方法 (1) 后端性能测试&#xff1a;其实&#xff0c;你平时听到的性能测试&#xff0c;大多数情况下指的是后端性能测试&#xff0c;也就是服务器端性能测试。后端性能测试&#xff0c;是通过性能测试工具模拟大量的并发用户请求&…

20240219画图程序

1. PTZ在惯性态时&#xff0c;不同视场角下的【发送】角速度和【理论响应】角速度 1.1 优化前 import numpy as np import matplotlib.pyplot as plt# PTZ在惯性态时&#xff0c;不同视场角下的【发送】角速度和【理论响应】角速度 ATROffset_x np.linspace(0, 60, 120) y2 …

OpenAI 全新发布文生视频模型 Sora,支持 60s 超长长度,有哪些突破?将带来哪些影响?

Sora大模型简介 OpenAI 的官方解释了在视频数据基础上进行大规模训练生成模型的方法。 我们下面会摘取其中的关键部分罗列让大家快速get重点。 喜欢钻研的伙伴可以到官网查看技术报告&#xff1a; https://openai.com/research/video-generation-models-as-world-simulator…

【图论经典题目讲解】CF786B - Legacy 一道线段树优化建图的经典题目

C F 786 B − L e g a c y \mathrm{CF786B - Legacy} CF786B−Legacy D e s c r i p t i o n \mathrm{Description} Description 给定 1 1 1 张 n n n 个点的有向图&#xff0c;初始没有边&#xff0c;接下来有 q q q 次操作&#xff0c;形式如下&#xff1a; 1 u v w 表示…

GO和KEGG富集分析

写在前面 我们《复现SCI文章系列教程》专栏现在是免费开放&#xff0c;推出这个专栏差不多半年的时间&#xff0c;但是由于个人的精力和时间有限&#xff0c;只更新了一部分。后续的更新太慢了。因此&#xff0c;最终考虑后还是免费开放吧&#xff0c;反正不是什么那么神秘的东…

关于数据结构的定义以及基本的数据结构

在计算机科学中&#xff0c;数据结构是指用于组织和存储数据的方式或方法。它涉及到在计算机内存中存储、管理和操作数据的技术和原则。数据结构不仅仅是简单地存储数据&#xff0c;还可以提供高效的数据访问和操作方式&#xff0c;以满足特定的需求。 以下是每个数据结构的详细…

mkcert安装教程

1、下载 官方文档&#xff1a;https://github.com/FiloSottile/mkcert#mkcert 下载链接&#xff1a;https://github.com/FiloSottile/mkcert/releases 2、安装&#xff0c;该文件目录下打开cmd&#xff08;可以把文件复制到别的文件夹&#xff09;&#xff0c;执行命令 //命令…

开源模型应用落地-工具使用篇-向量数据库进阶(四)

一、前言 通过学习"开源模型应用落地"系列文章&#xff0c;我们成功地建立了一个完整可实施的AI交付流程。现在&#xff0c;我们要引入向量数据库&#xff0c;作为我们AI服务的二级缓存。本文将继续基于上一篇“开源模型应用落地-工具使用篇-向量数据库&#xff08;三…

FreeRTOS移植到GD32

目录 一、GD32基础工程创建&#xff1a; 1、创建如下文件夹 2、在keil5创建工程 3、在工程添加相关.c文件和头文件路径 4、实例&#xff1a;实现LED闪烁功能 二、在基础工程添加FreeRTOS&#xff1a; 1、FreeRTOS中的文件: 2、添加的源文件: 3、添加的头文件路径: 4、…

机器人常用传感器分类及一般性要求

机器人传感器的分类 传感技术是先进机器人的三大要素&#xff08;感知、决策和动作&#xff09;之一。根据用途不同&#xff0c;机器人传感器可以分为两大类&#xff1a;用于检测机器人自身状态的内部传感器和用于检测机器人相关环境参数的外部传感器。 内部传感器 内部传感…

【JavaEE】_HTML常用标签

目录 1.HTML结构 2. HTML常用标签 2.1 注释标签 2.2 标题标签&#xff1a;h1~h6 2.3 段落标签&#xff1a;p 2.4 换行标签&#xff1a;br 2.5 格式化标签 2.6 图片标签&#xff1a;img 2.7 超链接标签&#xff1a;a 2.8 表格标签 2.9 列表标签 2.10 表单标签 2.10…

航班进出港|航班进出港管理系统|基于springboot航班进出港管理系统设计与实现(源码+数据库+文档)

航班进出港管理系统目录 目录 基于springboot航班进出港管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 5、航班信息管理 &#xff08;1&#xff09; 航班信息管理 &#xff08;2&#xff09;起飞降落申请管理 &#xff08;3&#xff09;公告管理 &…

辽宁博学优晨教育科技有限公司视频剪辑培训专业之选

随着数字时代的到来&#xff0c;视频剪辑技术已成为各行各业不可或缺的一项技能。为了满足市场需求&#xff0c;辽宁博学优晨教育科技有限公司&#xff08;以下简称“博学优晨”&#xff09;推出了专业的视频剪辑培训课程&#xff0c;旨在为广大学员提供系统、高效的学习机会。…

AMD FPGA设计优化宝典笔记(4)复位桥

高亚军老师的这本书《AMD FPGA设计优化宝典》&#xff0c;他主要讲了两个东西&#xff1a; 第一个东西是代码的良好风格&#xff1b; 第二个是设计收敛等的本质。 这个书的结构是一个总论&#xff0c;加上另外的9个优化&#xff0c;包含的有&#xff1a;时钟网络、组合逻辑、触…

面试系列之《Spark》(持续更新...)

1.job&stage&task如何划分&#xff1f; job&#xff1a;应用程序中每遇到一个action算子就会划分为一个job。 stage&#xff1a;一个job任务中从后往前划分&#xff0c;分区间每产生了shuffle也就是宽依赖则划分为一个stage&#xff0c;stage这体现了spark的pipeline思…

picker选择器-年月日选择

从底部弹起的滚动选择器。支持五种选择器&#xff0c;通过mode来区分&#xff0c;分别是普通选择器&#xff0c;多列选择器&#xff0c;时间选择器&#xff0c;日期选择器&#xff0c;省市区选择器&#xff0c;默认是普通选择器。 学习一下日期选择器 平台差异说明 日期选择默…

k8s学习(RKE+k8s+rancher2.x)成长系列之简配版环境搭建(三)

3.19.切换RKE用户,并做免密登录(三台机器相互免密) su rke cd~ ssh-keygen[rke@master.ssh]$ssh-copy-id rke@slaver2 [rke@master.ssh]$ssh-copy-id rke@slaver1 [rke@master.ssh]$ssh-copy-id rke@master3.20.搭建RKE集群 为了方便理解,我们把通RKE部署的Kubernetes集群称…

浏览网页记录工具,企业如何查看员工网页浏览记录

随着信息技术的飞速发展&#xff0c;网络已成为企业日常运营和员工工作中不可或缺的一部分。然而&#xff0c;随之而来的是网络安全和员工上网行为管理的挑战。在这种情况下&#xff0c;浏览网页记录工具成为了企业监控员工上网行为的重要手段之一。 一、浏览网页记录工具的重要…

MySQL 基础知识(十)之 MySQL 架构

目录 1 MySQL 架构说明 2 连接层 3 核心业务层 3.1 查询缓存 3.2 解析器 3.3 优化器 3.4 执行器 4 存储引擎层 5 参考文档 1 MySQL 架构说明 下图是 MySQL 5.7 及其之前版本的逻辑架构示意图 MySQL 架构大致可分为以下三层&#xff1a; 连接层&#xff1a;负责跟客户…