C语言中一些有关字符串的常见函数的使用及模拟实现(2)

在编程的过程中,我们经常要处理字符和字符串,为了⽅便操作字符和字符串,C语⾔标准库中提供了\n⼀系列库函数,接下来我们就学习⼀下这些函数。

在上一篇博客中已经讲解了strlen,strcpy,strcmp,stccat这几个字符串相关的函数。
接着,再为大家介绍几个库函数,

strncpy,strncat,strncmp
同样包含在头文件string.h中
这三个函数都只是在中间加了个”n“,现在,来详细认识一下这三个库函数。

文章目录

  • strncpy函数
  • strncat函数
  • strncmp函数
  • strstr函数
  • memcpy函数

strncpy函数

看名字就知道,strncpy函数与strcpy函数是比较相似的,都是将一个字符串拷贝到另一个字符串中,不一样的是strncpy参数中多一个size_t类型的参数

在这里插入图片描述

这个参数的意思就是限制这个字符串的拷贝

在这里插入图片描述
这个例子就表示拷贝前5个字符,

来模拟实现一下这个库函数。

//strncpy的函数模拟实现
#include<stdio.h>
#include<assert.h>


char* my_strncpy(char* s1,const char* s2,size_t n)
{
	assert(s1 && s2);
	char* ret = s1;
	while (n--&&(*s1 = *s2))
	{
		s1++;
		s2++;
	}
	return ret;
}




int main()
{
	char arr1[20] = "abcdef";
	char arr2[20] = "ghijk";
	char*ret = my_strncpy(arr1, arr2, 3);
	printf("%s", ret);
	return 0;
}

strncat函数

相信你在了解了strncpy函数之后,就大概可以猜出来strncat函数就是有限制的去追加一个字符串

在这里插入图片描述
看一个例子帮助理解
在这里插入图片描述

直接来看代码实现吧。

char* my_strncat(char* s1, char* s2, size_t n)
{
	assert(s1 && s2);
	char* ret = s1;
	while (*s1 != '\0')
	{
		s1++;
	}
	while (n-- && (*s1 = *s2))
	{
		*s1++;
		*s2++;
	}
	return ret;
}


int main()
{
	char arr1[20] = "abcdef";
	char arr2[20] = "ghijk";
	char*ret = my_strncat(arr1, arr2, 1);
	printf("%s", ret);
	return 0;
}

strncmp函数

⽐较str1和str2的前num个字符,如果相等就继续往后⽐较,最多⽐较num个字⺟,如果提前发现不⼀样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0.

在这里插入图片描述

看上面这个例子,因为只比较了前四个字符,是相等的,所以返回0

在这里插入图片描述
该函数的返回类型是int类型。

来看一下这个函数的模拟实现

#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* str1, const char* str2,size_t num)
{
	int ret = 0;
	assert(str1 != NULL);
	assert(str2 != NULL);
	while (*str1 == *str2&&num--)
	{
		if (num == 0)
		{
			return 0;
		}
		str1++;
		str2++;
	}

	return *str1 - *str2;
}

int main()
{
	char arr1[10] = "abcdef";
	char arr2[10] = "abcdfg";
	int ret = my_strncmp(arr1,arr2,3);
	printf("%d", ret);
	return 0;
}

strstr函数

strstr函数是字符串中寻找子字符串的一个库函数。该函数的返回类型是char*类型,返回的是找到子字符串的第一个元素的地址,例如,在abcdef中查找一个cde,返回字符c的地址。
在这里插入图片描述

在这里插入图片描述
该函数返回类型是char*类型。

这个函数的模拟实现比之前略微增加一些难度,比如你在abcccdef中查找ccd,别慌,我们有解决方案,只需要做一个标记,下一次查找时直接从标记的下一个字符开始查找

char* my_strstr(const char* s1, const char* s2)
{
	assert(s1 && s2);//asser断言检查s1,s2是否是空指针
	char* cur = s1;//cur作为一个标记
	char* a1 = NULL;
	char* a2 = NULL;

	while (*cur)//cur到'\0'是还没有找到子字符串则返回空指针NULL。
	{
		a1 = cur;//从第二个字符开始遍历查找
		a2 = s2;
		while (*s1&&*s2&&*a1 == *a2)
		{
			*a1++;
			*a2++;
		}
		if (*a2 == '\0')//子字符串到'\0'时,表示找到了,返回指针cur
			return (char*)cur;
		cur++;
	}
	return NULL;
}

memcpy函数

在这里插入图片描述
这个函数又比strncpy函数高级了一点,它的参数和返回类型都都是void类型的,表示这不仅可以拷贝字符串,也可以拷贝数字数组了。

如下:

在这里插入图片描述来看一下它的模拟实现

void* my_memcpy(void* s1, const void * s2, size_t n)
{
	assert(s1 && s2);
	void* ret1 = s1;
	while (n--)
	{
		*(char*)s1 = *(char*)s2;
		*((char*)s1)++;
		*((char*)s2)++;
	}
	return ret1;
}

我们自己模拟实现的函数能否自己拷贝自己呢?
在这里插入图片描述
很明显,这是与我们想达到的效果是不一样的,它不能自己拷贝自己。
原因是当把1,2拷贝到3,4上时,3,4被改变成了1,2.所以不能自己拷贝自己。
但是库函数可以实现这个功能。
在这里插入图片描述
但是memcpy函数本身就没有要求自己拷贝自己,所以,我们的函数模拟实现还是没有问题的。
可以说编译器实现的库函数还是很厉害的。

C语言也有一个专门用来自己拷贝自己的库函数memmove
这里我们把模拟实现的代码放在这里,感兴趣的可以看一看。

从前向后拷贝和从后向前拷贝的方式时不一样的,所以要分类讨论一下

void* my_memmove(void* dest, const void* str, size_t n)
{
	assert(dest && str);
	void* ret = dest;
	if (dest < str)
	{
		while (n--)
		{
			*((char*)dest) = *((char*)str);
			(char*)dest = (char*)dest + 1;
			(char*)str = (char*)str + 1;
		}
	}
	else
	{
		while (n--)
		{
			*(((char*)dest)+n) = *(((char*)str)+n);
		}
	}
	return ret;
}

这就是几个字符串的简单讲解了,希望你能通过我的文章收获一些知识。

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

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

相关文章

XXL-Job详解(二):安装部署

目录 前言环境下载项目调度中心部署执行器部署 前言 看该文章之前&#xff0c;最好看一下之前的文章&#xff0c;比较方便我们理解 XXL-Job详解&#xff08;一&#xff09;&#xff1a;组件架构 环境 Maven3 Jdk1.8 Mysql5.7 下载项目 源码仓库地址链接: https://github.…

el-drawer抽屉组件弹窗遮挡问题解决

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 1、根据需要&#xff0c;需要在下面窗口里弹出抽屉组件&#xff0c;但出现遮挡问题&#xff0c;如下&…

阿里云刚崩完又崩了?部分地域云数据库控制台访问异常

11月27日&#xff0c;阿里云发布公告&#xff1a;您好&#xff01;北京时间2023年11月27日 09:16起&#xff0c;阿里云监控发现北京、上海、杭州、深圳、青岛 、香港以及美东、美西地域的数据库产品&#xff08;RDS、PolarDB、Redis等&#xff09;的控制台和OpenAPI访问出现异常…

【Openstack Train安装】一、虚拟机创建

Openstack是一个云平台管理的项目&#xff0c;它不是一个软件。这个项目由几个主要的组件组合起来完成一些具体的工作。Openstack是一个旨在为公共及私有云的建设与管理提供软件的开源项目。它的社区拥有超过130家企业及1350位开发者&#xff0c;这些机构与个人将 Openstack作为…

【Windows】内网穿透实现hMailServer远程发送邮件

目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpolar内网…

【RedisTemplate】SpringDataRedis(Spring中对Redis模块的整合)

SpringDataRedis简介&#xff1a; SpringData是Spring中数据操作的模块&#xff0c;包含对各种数据库的集成&#xff0c;其中对Redis的集成模块就叫做SpringDataRedis。 官网地址&#xff1a;https://spring.io/projects/spring-data-redis 提供了对不同Redis客户端的整合&a…

C++学习之路(十四)C++ 用Qt5实现一个工具箱(增加一个Base64图片编码预览功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《Base64加解密功能》功能。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加一个平时经常用到的功能吧&#xff0c;就是「 Base64图片编码预览 」功能。下面我们就来看看如何来规划开发一个这样的小功能并且添加…

Redis的高可用模式

1. 什么是高可用&#xff1f; 高可用&#xff08;High Availability, HA&#xff09;是指在信息技术中确保系统、服务或应用程序在绝大多数时间内都是可操作和可访问的能力。这通常涉及以下几个关键方面&#xff1a; 最小化停机时间: 高可用系统的目标是减少因硬件故障、系统升…

无mac电脑生成uniapp云打包私钥证书的攻略

uniapp顾名思义是一个跨平台的开发工具&#xff0c;大部分uniapp的开发者&#xff0c;其实并没有mac电脑来开发&#xff0c;但是生成ios的证书&#xff0c;官网的教程却是需要mac电脑的&#xff0c;那么有没有办法无需mac电脑即可生成uniapp云打包的私钥证书呢&#xff1f; 下…

小白都能看懂的手把手详细Git安装教程

什么是Git Git是一个源代码管理系统&#xff0c;旨在帮助开发人员协同工作。它是一个分布式的版本控制系统&#xff0c;可以有效地将代码库分支、合并和版本控制&#xff0c;同时还可以跟踪文件的更改、修改内容并保留历史记录。Git能够让多个开发人员同时对同一代码库进行协作…

Linux基础篇-开机自动挂载

目录 开机挂载的几种方法/etc/fstab/etc/rc.local或/etc/rc.d/rc.local 开机挂载的几种方法 修改配置文件/etc/fstab &#xff08;如果是磁盘信息输错&#xff0c;那么系统重启时会进入维护模式&#xff0c;影响操作系统的正常运行.&#xff09; 在/etc/rc.local内添加挂载命令…

基于ASP.NET MVC技术的图书管理系统的设计与实现

基于ASP.NET MVC技术的图书管理系统的设计与实现 摘要&#xff1a;图书管理系统是一套高新科学技术和图书知识信息以及传统历史文化完美结合的体现。它改变了传统图书收藏的静态书本式图书服务特征&#xff0c;实现了多媒体存取、远程网络传输、智能化检索、跨库无缝链接、创造…

WebSocket入门介绍及编程实战

HTTP的限制 全双工和半双工&#xff1a; 全双工&#xff1a;全双工&#xff08;Full Duplex&#xff09;是允许数据在两个方向上同时传输。 半双工&#xff1a;半双工&#xff08;Half Duplex&#xff09;是允许数据在两个方向上传输&#xff0c;但是同一个时间段内只允许一个…

三维模型的顶层合并构建的轻量化技术方法探讨

三维模型的顶层合并构建的轻量化技术方法探讨 倾斜摄影超大场景的三维模型的顶层合并构建通常会生成庞大的数据量&#xff0c;给存储、传输和处理带来很大的挑战。为了解决这个问题&#xff0c;可以采用轻量化处理技术&#xff0c;以减小数据体积、提高处理效率&#xff0c;并方…

GAN:WGAN-GP-带有梯度惩罚的WGAN

论文&#xff1a;https://arxiv.org/pdf/1704.00028.pdf 代码&#xff1a;GitHub - igul222/improved_wgan_training: Code for reproducing experiments in "Improved Training of Wasserstein GANs" 发表&#xff1a;2017 WGAN三部曲的终章-WGAN-GP 摘要 WGAN在…

APITable免费开源的多维表格与可视化数据库本地部署公网远程访问

APITable免费开源的多维表格与可视化数据库公网远程访问 文章目录 APITable免费开源的多维表格与可视化数据库公网远程访问前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c…

QQ小程序分销商城源码系统 带完整的搭建教程

互联网的快速发展&#xff0c;电商行业也迅速崛起&#xff0c;如今线上购物已经成为许多人日常生活的一部分。然而&#xff0c;随着竞争的加剧&#xff0c;电商企业需要不断创新和优化&#xff0c;以吸引更多的消费者和提高销售额。在这个背景下&#xff0c;我们开发了QQ小程序…

JavaEE——简单认识CSS

文章目录 一、简单了解什么是 CSS二、CSS 选择器1.标签选择器2.类选择器3.ID 选择器4.后代选择器5.子选择器6.伪类选择器 三、字体属性1.设置字体家族2.设置字体大小3.设置字体粗细4.文字倾斜 四、文本属性1.文本对齐2.文本装饰3.文本缩进4.背景设置 五、圆角矩形六、CSS 盒子模…

将不同时间点的登录状态记录转化为不同时间段的相同登录状态SQL求解

题目 有不同时间点的登录状态记录表state_log如下 请使用sql将其转化为如下表的不同时间段的相同登录状态记录 思路分析&#xff1a; 此类问题需要用到lag或lead函数取上下行对应的数据&#xff0c;然后对前后结果做比较打标签&#xff08;0或1&#xff09;&#xff0c;再…

List集合,遍历,数据结构

一.List常见的方法&#xff1a; 二. List集合的遍历方式 除了 迭代器遍历 增强for遍历 Lambda表达式遍历&#xff0c;还有自己独有的普通for遍历&#xff0c;列表迭代器遍历 1.迭代器遍历 2.增强for遍历 3.Lambda表达式遍历 4.普通for遍历 5.列表迭代器遍历 列表迭代器相对于…