<string.h>中一些函数的使用和模拟实现

strcpy的使用和模拟实现

strcpy的使用

strcpy,拆开是string copy,即字符串拷贝,作用是将字符串从一个位置拷贝到另一个位置,它的函数原型如下:

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

其中destination是指向目标字符串的指针,source是指向源头字符串的指针。
它需要一个源头字符串和目标字符串,它会将源头字符串复制到目标字符串中。
我们来使用一下:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = { '0' };
	char arr2[] = "abcdef";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

结果为:
在这里插入图片描述
那么arr2字符串末尾的\0有没有被复制过去呢?我们来测试一下:
在这里插入图片描述

调试可知\0确实被拷贝过去了。

注意事项

  • 1 .源头字符串要不可修改,目标字符串要可修改。
    1. 源头字符串要以\0结尾
  • 3.目标字符串要有足够大的空间以存放源头字符串,例如char arr1[20]就留出了20个元素的空间。

strcpy的模拟实现

我们需要两个指针dest和src,分别指向arr1和arr2,*src赋值给*dest后,两个指针同时向后移动一个单位,再次进行赋值操作,直到*src == ‘\0’。再单独将\0赋值给arr1

在这里插入图片描述
代码:

#include <stdio.h>
#include <string.h>
char* my_strcpy(char* dest, char* src)
{
  char* ret = dest;
	while (*src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	if (*src == '\0')
	{
		*dest = *src;
	}
	return ret;
}
int main()
{
	char arr1[20] = "xxxxxxxxxxxxxxxxxxxx";
	char arr2[] = "abcdef";
	my_strcpy(arr1, arr2);
	return 0;
}

当然我们可以优化一下:

arr2不能被修改,我们就在src前加一个const修饰。
为了防止dest和src是野指针,我们可以加一个assert断言。
我们也可以把‘\0’的赋值融到上一段代码中。

优化后为:

#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest != NULL && src != NULL);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "xxxxxxxxxxxxxxxxxxxx";
	char arr2[] = "abcdef";
	printf("%s\n", my_strcpy(arr1, arr2));
	return 0;
}

下面的代码实现了既能打印正常字符又能打印’\0’,因为后置++是先使用,再加1,*src先赋值给*dest,然后src再加1,直到*src = '\0'赋值给*dest后,while停止循环。

while (*dest++ = *src++)
	{
		;
	}

strcat的使用和模拟实现

strcat的使用

strcat实现的是字符串追加,即将源头字符串加在目标字符串的后边。
strcat的函数原型如下:

char* strcat(char* dest,const char* src)

我们来使用一下:

#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
	char arr1[20] = "abc";
	char arr2[] = "def";
	strcat(arr1,arr2);
	printf("%s\n", arr1);
	return 0;
}

结果:
在这里插入图片描述
可见"def"成功加在了"abc"的后面。

源头字符串的’\0’也加在了后面,可以自己调试验证一下。

注意事项

  • 1.源头字符串必须以’\0’结束
  • 2.目标空间要足够大
  • 3.目标字符串要可修改

strcat的模拟实现

为了实现追加,我们要让src指针移动到源头字符串‘\0’的位置,然后在进行逐个拷贝的操作,当然我们要记录一下dest的起点ret
在这里插入图片描述
代码为:

#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "abcd";
	char arr2[] = "efg";
	printf("%s\n", my_strcat(arr1, arr2));
	return 0;
}

那么问题来了,我们可不可以给字符串自身追加它自身呢?我们来分析一下:
dest遇到\0后开始拷贝,\0被修改为a,当src遇到原\0的位置时,遇到的实际上是a,造成src无法停止并循环拷贝,结果为abcabcabcabc…
在这里插入图片描述

strcmp的使用和模拟实现

strcmp的使用

strcmp 函数是 C 语言中用于比较两个字符串的函数,其声明如下:
• 函数原型:

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

• 参数:
• str1: 要比较的第一个字符串。
• str2: 要比较的第二个字符串。
• 返回值:
• 如果返回值小于 0,表示 str1 小于 str2。
• 如果返回值大于 0,表示 str1 大于 str2。
• 如果返回值等于 0,表示两个字符串相等
那么如何判断两个字符串?⽐较两个字符串中对应位置上字符ASCII码值的⼤⼩。

strcmp的模拟实现

 int my_strcmp (const char * str1, const char * str2)
 {
 int ret = 0 ;
 assert(str1 != NULL);
 assert(str2 != NULL);
 while(*str1 == *str2)
 {
 if(*str1 == '\0')
 return 0;
 str1++;
 str2++;
 }
 return *str1-*str2

strstr的使用和模拟实现

strstr的使用

strstr,即string string,作用是在字符串中查找特定字符串,例如在“abcdefg”中找出“cde”.它的函数原型如下:

 char *strstr(const char *str1, const char *str2)

函数会返回字符串str2在字符串str1中第⼀次出现的位置。
我们使用一下:

#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
	char arr1[] = "abcdefgh";
	char arr2[] = "def";
	char* p = strstr(arr1, arr2);
	printf("%s\n", p);
	return 0;
}

结果:
在这里插入图片描述

strstr的模拟实现

我们需要将*str1*str2进行逐个比较,判断*str1*str2是否相等,当str2找到\0的时候结束并返回str1与str2开始相等的位置。
在这里插入图片描述
但我们还需要str1,str2的初始位置以便于发现不相等之后重新判断,所以我们要再引用两个指针s1,s2进行移动,而str1和str2的位置固定不变。
在这里插入图片描述
然后我们还需要一个指针cur用来记录开始匹配成功的位置。
在这里插入图片描述

char* my_strstr(char* str1, char* str2)
{
	char* s1 = str1;
	char* cur = str1;
	while (*s1)
	{
		char* s2 = str2;
		if (*s1 == *s2)
		{
			cur = s1;
			while (*s1 == *s2&&*s2 != '\0')
			{
				s1++;
				s2++;
			}
		}
		if (*s2 == '\0')
		{
			return cur;
		}
		
		s1++;
	}
	return NULL;
}

但当这种情况时,s1,s2匹配失败后又需要s1回到cur的位置并+1移动到下一个位置继续匹配,所以我们再添一段代码:
在这里插入图片描述

char* my_strstr(char* str1, char* str2)
{
	char* s1 = str1;
	char* cur = str1;
	while (*s1)
	{
		char* s2 = str2;
		if (*s1 == *s2)
		{
			cur = s1;
			while (*s1 == *s2&&*s2 != '\0')
			{
				s1++;
				s2++;
			}
		}
		if (*s2 == '\0')
		{
			return cur;
		}
		if (*cur == *(cur + 1))
		{
			s1 = cur;
		}
		s1++;
	}
	return NULL;
}
int main()
{
	char arr1[] = "abcdefgbcqffff";
	char arr2[] = "bcq";
	char* p = my_strstr(arr1, arr2);
	if (p == NULL)
	{
		printf("找不到");
	}
	printf("%s\n", p);
	return 0;
}

最后再考虑一下特殊情况就完成了:

#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strstr(char* str1, char* str2)
{
	assert(str1 && str2);
	if (*str2 == '\0' || *str1 == '\0')
	{
		return NULL;
	}
	char* s1 = str1;
	char* cur = str1;
	while (*s1)
	{
		char* s2 = str2;
		if (*s1 == *s2)
		{
			cur = s1;
			while (*s1 == *s2&&*s2 != '\0')
			{
				s1++;
				s2++;
			}
		}
		if (*s2 == '\0')
		{
			return cur;
		}
		if (*cur == *(cur + 1))
		{
			s1 = cur;
		}
		s1++;
	}
	return NULL;
}
int main()
{
	char arr1[] = "abcdefgbcqffff";
	char arr2[] = "bcq";
	char* p = my_strstr(arr1, arr2);
	if (p == NULL)
	{
		printf("找不到");
	}
	printf("%s\n", p);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值