strcpy,strcat,strstr,memcpy以及memmove的模拟实现

目录

导读:

1.strcpy函数

1.1strcpy函数的作用及基本用法

1.2注意:

1.3模拟实现strcpy 函数

2.strcat函数

2.1strcat函数的作用及基本用法 

2.2注意:

2.3模拟实现 strcat函数

3.strstr函数

3.1strstr函数的作用及基本用法

3.2模拟实现strstr函数 

4.memcpy函数

4.1memcpy函数的作用及基本用法

4.2注意:

4.3模拟实现 memcpy函数

5.memmove函数

5.1memmove函数的作用及基本用法

5.2注意:

5.3模拟实现memmove函数 

5.3.1注意:

5.3.2代码实现:


 

导读:

strcpy strcat和strstr为字符串函数

memcpy和memmove则为内存函数

本文我们将会讲到这些函数的使用以及如何自身模拟实现

每个模拟实现的代码内也配有注释

1.strcpy函数

1.1strcpy函数的作用及基本用法

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

strcpy是stringcopy的简写,表示”字符串复制函数“,作用是将source指向的字符串复制到 destination指向的函数中去。

1.2注意

  • 源字符串必须以 '\0' 结束。
  • 会将源字符串中的 '\0' 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。

1.3模拟实现strcpy 函数

char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;//保存目标空间的起始地址
	while ((*dest++ = *src++))
	{
		;
	}
	return ret;//返回目标
}
int main()
{
	char arr1[100] = { 0 };
	char arr2[] = "Hello world!";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 

2.strcat函数

2.1strcat函数的作用及基本用法 

strcat —— 字符串连接函数 一般形式如下:

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

调用形式strcat(字符数组1,字符数组2),把源字符串连接到目标字符串后面,结果放在目标字符数组中,函数调用后得到一个函数值——目标字符串的地址

2.2注意:

  • 源字符串必须以 '\0' 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。

2.3模拟实现 strcat函数

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;//记录目标字符串的起始地址
	while (*dest != '\0')//先进入循环,一直到它本身字符内容的后面
	{
		dest++;
	}
	while (*dest++ = *src++)//把src解引用赋值给dest,包括'\0'
	{
		;
	}
	return ret;//返回目标字符串的起始地址
}
int main()
{
	char arr1[100] = "Hello";
	char arr2[] = " world!";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 

3.strstr函数

3.1strstr函数的作用及基本用法

strstr函数用于在一个字符串中查找另一个字符串的第一次出现位置,并返回该位置的指针 

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

str1是要被搜索的字符串,str2是要搜索的字符串。

如果str2是空字符串则返回str1

如果str2没有在str1中出现则返回NULL。

3.2模拟实现strstr函数 

const char* my_strstr(const char* str1, const char* str2)
{
	const char* cp;//记录开始匹配的位置
	const char* s1;//遍历str1
	const char* s2;//遍历str2
	if (*str2 == '\0')//如果str2为空,直接返回
	{
		return str1;
	}
	cp = str1;//指向str1起始位置
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)//*s1 *s2不指向\0,s1 = s2进入循环
		{
			s1++;//往后加开始遍历
			s2++;
		}
		if (*s2 == '\0')//循环结束后,如果s2为'\0'表面已经找到
		{
			return cp;
		}
		cp++;//循环结束后,s2不为'\0'说明还没有找到,cp自加一
	}
	return NULL;
}
int main()
{
	char arr1[] = "abbbcd";
	char arr2[] = "bbc";
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n",ret);
	}
	return 0;
}

 

4.memcpy函数

4.1memcpy函数的作用及基本用法

 是将一段内存区域的数据复制到另一个内存区域。它可以用来实现结构体、数组等复杂数据类型的复制。

void * memcpy ( void * destination, const void * source, size_t num );

destination表示目标内存区域的地址,source表示源内存区域的地址,num表示要复制的字节数。

4.2注意:

  • 目标内存区域和源内存区域不能重叠,否则结果会不可预料。
  • 要复制的字节数num不能超过目标内存区域和源内存区域的有效长度,否则会造成越界访问的错误。
  • 该函数从src指向的内存地址开始,向后复制num个字节到destination指向的内存地址开始处

4.3模拟实现 memcpy函数

void* my_memcpy(void* dest, void* src, size_t sz)
{
	while (sz--)
	{
		*(char*)dest = *(char*)src;//由于memcpy函数是以字节为单位进行copy
		//int类型为四个字节,所以这里需要强转为char*类型,一个字节一个字节的复制
		dest = (char*)dest + 1;//强转类型都是临时的,并不会永远改变类型
		src = (char*)src + 1;//所以这里仍需再次强转为char*
	}
}
int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 0,9,2,6 };
	my_memcpy(arr1, arr2, 16);//16个字节,也就是4个int类型
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

 

5.memmove函数

5.1memmove函数的作用及基本用法

其作用是在内存区域移动一定数量的字节,并返回指向目标内存区域的指针。
与memcpy函数作用类似

void * memmove ( void * destination, const void * source, size_t num );

destination表示目标内存区域的指针,source表示源内存区域的指针,num表示要移动的字节数。

 

5.2注意:

  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

5.3模拟实现memmove函数 

5.3.1注意:

由于在移动中,可能出现前面的值移动到后面,把重叠内存的值给改变
到把重叠内存的内容再往后移动时,该区域原先的值已发生改动
最初值丢失导致与预想的结果不一样,所以这里要区分情况

5.3.2代码实现:

void* my_memmove(void* dest, const void* src, size_t sz)
{
	void* ret = dest;//记录目标字符串的起始地址

	//如把后面的内存指针移动到前面
	//移动轨迹为从前到后,先改变目标内存前面的内容,再依次改变后面的内存
	if (dest < src)
	{
		while (sz--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	//如果把前面的内存区域移动到后面的内存区域
	//移动轨迹为从后到前,先改变目标内存后面的内容,再依次改变前面的
	else
	{
		while (sz--)
		{
			*((char*)dest + sz) = *((char*)src + sz);
		}
	}
	return ret;
}
int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	my_memmove(arr, arr + 1, 16);//从第2个元素开始往后数4个元素,移动到下标为0的内存中
	int i = 0;
	for (i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流浪者与猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值