C语言字符串类型部分库函数使用和模拟实现(2)


书接上文,上次简单总结了strlen、strcmp、strcpy、strcat、strtok这几个函数的使用和模拟。这次总结以下strstr、strn开头的几个函数、atoi等字符串操作函数和模拟实现。

一、strstr的使用和模拟实现

1. strstr的使用

strstr函数的作用是查找一个字符串中是否包含另一个字符串,及一个字符串是否是另一个字符串的子串。倘若是,则返回原字符串中包含字符串的首元素地址,否则返回空指针。可以看到strstr的函数声明是这样的:
在这里插入图片描述
函数的使用效果如图所示:
在这里插入图片描述
当函数没有找到相同字符串的时候,就会返回空指针
在这里插入图片描述

2. strstr模拟实现

知道了该函数的效果,参数和返回类型后,我们可以来模拟一下strstr函数

char* strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);//避免参数传了空指针,NULL的值为0;
	const char* tmp1 = str1;
	const char* tmp2 = str2;
	while(*str1)
	{
		while(*str1 != *str2)//在str1中找第一个字符与str2首字符相同的;
		{
			str1++;
			tmp1++;//用tmp1来记住首元素地址;
			if(*str1 == '\0')//当str指向'\0'的时候,说明找不到了
				return NULL;
		}
		while(*str1 == *str2)//找到首字符相同的之后,判断剩下的等不等;
		{
			str1++;
			str2++;
			if(*str2 == '\0')
			{
				return (char*)tmp1;//const char*转换为char*,免得报警告
			}
		}//如果中间出现不相同的字符,则跳出此循环,重置str1和str2;
		str1 = tmp1;
		str2 = tmp2;
		str1++;//找下一个字符;
	}
	return NULL;//当str指向最后的一个字符的时候,说明找不到了
}

根据逻辑初步的模拟就完成了,可以看到,效果和库函数相差无几:
在这里插入图片描述
但是我们可以发现,代码中有很多冗余,如外层循环的判断和内层循环的判断逻辑是一致的,因此我们可以稍作修改

char* strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);//避免参数传了空指针,NULL的值为0;
	const char* p1 = str1;
	const char* p2 = str2;
	for(; *p2; p1++,p2++)
	{
		for(; *p1 != *p2; p1++,str1++)
		{
			p2 = str2;//第二次进来是,把p2给初始化到首字符的位置;
			if(*p1 == '\0')
				return NULL;
		}
	}
	return (char*)str1;
}

这一次将两次对于str1的判断整合到一块去了,把调整部分整合进了for循环,看着就紧凑了许多。并且全程没有动str1和str2,保证了其不会被修改。

二、strncmp的使用和模拟实现

1. strncmp的使用

长话短说,strncmp和strcmp作用一样,多出来的n也是传参时的一个参数,为比较的字节个数,其形式如下:
在这里插入图片描述
其它的东西在上一篇已经提到过,在此不再赘述。

2. strncmp的模拟实现

代码如下(示例):

int strncmp(const char* str1, const char* str2, int count)
{
	for(;count--;str1++,str2++)
	{
		if((*str1 != *str2) || (*str1 == 0) || (*str2 == 0))
			return *str1 - *str2;	
	}
	return 0;
}

核心思想就是这么简洁易懂,另一个版本也是一样

int strncmp(const char* str1, const char* str2, int count)
{
	while(count--)
	{
		for (; (*str1 == *str2) && (*str1) && (*str2); str1++, str2++);
			return *str1 - *str2;
	}
	return 0;
}

本质上是一个意思。至于VS版本的-1,0,1的返回值在此就省略了。

三、strncpy的使用和模拟实现

1. strncpy的使用

同上,略过使用说明,加了一个n限制拷贝的字符数,其他使用事宜见上一篇。

在这里插入图片描述

2. strncpy的模拟实现

也很简单,甚至比strcpy还简单,在此直接给出

char* strncpy(chat* str1,const char* str2,int count)
{
	char* p = str1;
	while(count--)
		*str1++ = *str2++;
	return p;
}

当然能不越界还是别越界的好。

四、strncat的使用和模拟实现

1. strncat的使用

同上,略过使用说明,加了一个n限制拷贝的字符数,其他使用事宜见上一篇。
在这里插入图片描述

2. strncat的模拟实现

char* strncat(chat* str1,const char* str2,int count)
{
	char* p = str1;
	for(; *str1; str1++);//找到str1的结束位置;
	for(; count--; str1++, str2++)
	{
		*str1 = *str2;
	}
	return p;//返回str1的起始位置;
}

总结

strn系列的函数解决了str中很容易出现的越界问题,由编程者自己来决定要使用多少个字符,可以有效的预防bug的产生,不过字符串操作函数终归只能操作字符串,涉及到整型方面的内容,我们还会使用到memory系列函数,而这就是下次的内容了。

日常记录总敲代码行数:3707

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值