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

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

在上一篇博客中已经讲解了strlen,strcpy,strcmp,stccat这几个字符串相关的函数。

接着,再为大家介绍几个库函数,

strncpy,strncat,strncmp

同样包含在头文件string.h中

这三个函数都只是在中间加了个"n",现在,来详细认识一下这三个库函数。

文章目录

strncpy函数

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

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

这个例子就表示拷贝前5个字符,

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

c 复制代码
//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函数就是有限制的去追加一个字符串

看一个例子帮助理解

直接来看代码实现吧。

c 复制代码
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类型。

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

c 复制代码
#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,别慌,我们有解决方案,只需要做一个标记,下一次查找时直接从标记的下一个字符开始查找

c 复制代码
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类型的,表示这不仅可以拷贝字符串,也可以拷贝数字数组了。

如下:

来看一下它的模拟实现

c 复制代码
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

这里我们把模拟实现的代码放在这里,感兴趣的可以看一看。

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

c 复制代码
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;
}

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

相关推荐
Fairy_sevenseven12 分钟前
【二十八】【QT开发应用】模拟WPS Tab
开发语言·qt·wps
蜡笔小新星20 分钟前
Python Kivy库学习路线
开发语言·网络·经验分享·python·学习
凯子坚持 c20 分钟前
C语言复习概要(三)
c语言·开发语言
无限大.31 分钟前
c语言200例 067
java·c语言·开发语言
余炜yw33 分钟前
【Java序列化器】Java 中常用序列化器的探索与实践
java·开发语言
无限大.34 分钟前
c语言实例
c语言·数据结构·算法
篝火悟者34 分钟前
问题-python-运行报错-SyntaxError: Non-UTF-8 code starting with ‘\xd5‘ in file 汉字编码问题
开发语言·python
Death20037 分钟前
Qt 中的 QListWidget、QTreeWidget 和 QTableWidget:简化的数据展示控件
c语言·开发语言·c++·qt·c#
六点半88838 分钟前
【C++】速通涉及 “vector” 的经典OJ编程题
开发语言·c++·算法·青少年编程·推荐算法
惜.己38 分钟前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5