运用指针模拟实现一些代码以及memcpy函数与memmove函数的区别

这篇博客通过指针模拟实现C语言中的字符串操作函数,包括strcat, strcpy, strstr, strchr, strcmp, memcpy和memmove。详细解释了每个函数的功能和使用注意事项,并提供了模拟代码及运行结果。文章还探讨了memcpy和memmove的区别,特别是在内存区域重叠时的情况处理。" 103280123,8615143,动作识别与预测分析:癌症与收入预测实践,"['数据分析', '机器学习', '预测模型', '数据转换', 'K-最近邻']
摘要由CSDN通过智能技术生成


学习以下代码的准备工作:

  1. 了解简单的指针知识

  2. 了解assert()函数
    原型在assert.h中,作用是如果其值为假(即为0),则终止程序

  3. 了解关键字const 、extern的基本用法
    const:修饰变量,让变量具有只读属性,保护变量使其不能直接被改变
    extern:声明外部函数、变量

  4. 了解两个指针相减的实质
    是两个指针之间经历的元素个数

  5. 了解基本的内存操作

以下代码都在VS2013环境中执行:

1.模拟实现strcat

  1. c函数原型:extern char* strcat(char *dest, const char *src)

  2. 函数功能:strcat是连接字符串的函数。把src所指向的字符串添加到dest结尾处(覆盖dest结尾处的’\0’)并添加’\0’

  3. 注意:两个参数所指向的内存区域不可以重叠,dest参数所指向的内存地址必须能容纳两个字符串连接后的大小。

  4. 模拟代码如下:

#include<stdio.h>
#include<assert.h>
char* my_strcat(char *dest, const char *src)
{
	char *ret = dest;
	assert(dest);
	assert(src);
	while (*(++dest))
	{
		;
	}
	while((*dest++ = *src++));
	return ret;

}
int main()
{
	char s1[10] = { 0 };
	const char s2[10] = { 0 };
	printf("Enter a str1:");
	scanf("%s", s1);
	printf("Enter a str2:");
	scanf("%s", s2);
	my_strcat(s1, s2);
	printf("%s", s1);
	system("pause");
	return 0;
}

运行结果

引用块内容

2.模拟实现strcpy

  1. c函数原型:char* strcpy(char *dest, const char *src)

  2. 函数功能:strcat是复制字符串的函数。把从src地址开始且含有’\0’的字符串复制到以dest开始的地址空间内

  3. 注意:两个参数所指向的内存区域不可以重叠,dest参数所指向的内存地址必须能容纳scr的字符串

  4. 模拟代码如下:

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char *dest, const char *src)
{
	char *ret = dest;
	assert(dest);
	assert(src);
	while (*dest++ = *src++);
	return ret;

}
int main()
{
	char s1[10] = { 0 };
	const char s2[10] = { 0 };
	printf("Enter a str1:");
	scanf("%s", s1);
	printf("Enter a str2:");
	scanf("%s", s2);
	my_strcpy(s1, s2);
	printf("%s", s1);
	system("pause");
	return 0;
}

运行结果如下:

引用块内容

3. 模拟实现strstr

  1. c函数原型:extern char* strstr(const char *str1, const char *str2)

  2. 函数功能:搜索str2在str1中的第一次出现,若找到返回字符串的其余部分(从匹配点开始),如果没有找到所搜索的字符串,则返回NULL

  3. 模拟代码如下:

#include<stdio.h>
#include<assert.h>
char* my_strstr(const char *dest, const char *src)
{

	char *s1 = 0;
	char *s2 = 0;
	assert(dest);
	assert(src);
	while (*dest)
	{
		s1 = dest;
		s2 = src;
		while ((*s1 == *s2) && (*s2) && (*s1))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return dest;
		dest++;

	}
	return NULL;
}
int main()
{
	const char s1[10] = { 0 };
	const char s2[10] = { 0 };
	printf("Enter a str1:");
	scanf("%s", s1);
	printf("Enter a str2:");
	scanf("%s", s2);
	if (my_strstr(s1, s2) != NULL)
	{

		printf("%s\n", my_strstr(s1, s2));
	}
	else
		printf("没有找到!\n");
	system("pause");
	return 0;
}

运行结果如下:

引用块内容

4.模拟实现strchr

  1. c函数原型:extern char* strchr(const char *s, char c)
  2. 函数功能:查找字符串s中首次出现字符c的位置
  3. 注意:返回首次出现c的位置的指针,返回的地址是字符串在内存中随机分配的地址再加上你所搜索的字符串在字符串中的位置,如果s中不存在c则返回NULL
  4. 模拟代码如下
#include<stdio.h>
#include<assert.h>
char* my_strchr(const char *dest, char c)
{
	
	
	assert(dest);
	assert(c);
	while (*dest)
	{
		if (*dest == c)
			return dest;
		dest++;
	}
	return NULL;
}
int main()
{
	const char s1[10] = { 0 };
	const char *s2=0;
	printf("Enter a str1:");
	scanf("%s", s1);
	printf("Enter a str2:");
	fflush(stdin);
	scanf("%c", &s2);
	if (my_strchr(s1, s2) != NULL)
	{
		printf("%d\n", my_strchr(s1, s2) - s1 + 1);//两个指针相减的实质是两个指针之间经历的元素个数
	}
	else
		printf("没有找到!\n");
	system("pause");
	return 0;
}

运行结果:

引用块内容

5. 模拟实现strcmp

  1. c函数原型:extern char* strcpy(const char *s1, const char *s2)

  2. 函数功能:比较两个字符串的大小

  3. 规则:当s1小于s2,返回负数;当s1==s2,返回0;当s1大于s2,返回正数。即:两个字符串自左向右逐个字符相比(按ASCII值大小比较),直到出现不同的字符或遇到’\0’为止

  4. 注意:这里只能比较字符串

  5. 模拟代码如下:

#include<stdio.h>
#include<assert.h>
int  my_strcmp(const char *dest, const char *src)
{
	
	assert(dest);
	assert(src);
	while ((*dest) && (*src))
	{

		if (*dest != *src)
		{
			return *dest - *src;
		}
		else
		{
			dest++;
			src++;
		}
	}
	if ((*dest == '\0') && (*src == '\0'))
		return 0;
	if (*dest == '\0')
		return -1;
	if (*src == '\0')
		return 1;
}
	
int main()
{
	const char s1[10] = { 0 };
	const char s2[10] = { 0 };
	printf("Enter a str1:");
	scanf("%s", s1);
	printf("Enter a str2:");
	scanf("%s", s2);
	if (my_strcmp(s1, s2) == 0)
		printf("相等!\n");
	if (my_strcmp(s1, s2) > 0)
		printf("s1>s2\n");
	if (my_strcmp(s1, s2) < 0)
		printf("s1<s2\n");
	system("pause");
	return 0;
}

运行结果:

引用块内容

6. 模拟实现memcpy

  1. c函数原型:void *my_memcpy(void *dest, const void *src,int count)
  2. 函数功能:各种类型数据的复制,由src所指内存区域复制count个字节到dest所指向内存区域
  3. 规则:两个参数所指向的内存区域不可以重叠,dest参数所指向的内存地址必须能容纳scr的内存空间
  4. 模拟代码如下:
#include<stdio.h>
#include<assert.h>
void *my_memcpy(void *dest, const void *src,int count)
{
	assert(dest);
	assert(src);
	char *dest1 = (char*)dest;
	char *src1 = (char*)src;
		while (count>0)
		{
			*dest1 = *src1;
			dest1++;
			src1++;
			count--;
		}
		return dest;
}
int main()
{
	const int s1[10] = { 0 };
	const int s2[10] = { 1,2,3,4,5,6 };
	int i = 0;
	int count = sizeof(s2);
	my_memcpy(s1, s2,count);
	for (i = 0; i < sizeof(s2) / sizeof(s2[0]);i++)
	printf("%d ", s2[i]);
	system("pause");
	return 0;
}

运行结果:

引用块内容

7.模拟实现memmove

  1. c函数原型:void *my_memcpy(void *dest, const void *src,int count)
  2. 函数功能:各种类型数据的复制,由src所指内存区域复制count个字节到dest所指向内存区域
  3. 注意:这个函数是memcpy函数的升级版,不用担心两个参数所指向的内存区域重叠问题
  4. 模拟代码如下:
#include<stdio.h>
#include<assert.h>
void *memmove(void *dest, const void *src,int count)
{
	assert(dest);
	assert(src);
	char *dest1 = (char*)dest;
	char *src1 = (char*)src;
	char *p = dest1+count;
	char *q = src1 + count;
	if ((dest1 - src1)<count)
	{
		while (p>=dest1)
		{
			*p = *q;
			p--;
			q--;
		}
	}
	else
		while (count>0)
		{
			*dest1 = *src1;
			dest1++;
			src1++;
			count--;
		}
		return dest;
}
int main ( )
{
	const int s[10] = { 1,2,3,4,5,6 };
	int *s2 = s;
	int *s1 = s + 2;
	int i = 0;
	int count = sizeof(s);
	my_memmove(s1, s2,count);
	for (i = 0; i < sizeof(s)/sizeof(s[0]);i++)
	printf("%d ", s1[i]);
	system("pause");
	return 0;
}

运行结果:

引用块内容

8. memmove和memcpy的区别

如图,一般dest和scr在空间中分配内存有四种情况

引用块内容
在memcpy函数中,是将scr中的数据从低地址到高地址一个字节一个字节的考到dest中,前三种情况都不会出现scr中还未复制到dest中的数据被覆盖的情况,但第四种情况,当(dest - src)小于要拷的数据的个数的时候,在memcpy函数中则会出错,如下面一段代码:

#include<stdio.h>
#include<assert.h>
void *my_memcpy(void *dest, const void *src,int count)
{
	assert(dest);
	assert(src);
	char *dest1 = (char*)dest;
	char *src1 = (char*)src;
		while (count>0)
		{
			*dest1 = *src1;
			dest1++;
			src1++;
			count--;
		}
		return dest;
}
int main ( )
{
	const int s[10] = { 1,2,3,4,5,6 };
	int *s2 = s;
	int *s1 = s + 2;
	int i = 0;
	int count = sizeof(s);
	my_memcpy(s1, s2,count);
	for (i = 0; i < sizeof(s)/sizeof(s[0]);i++)
	printf("%d ", s1[i]);
	system("pause");
	return 0;
}

这里写图片描述
所以我们要从scr中的最后一个字符开始拷贝到dest中,即在memmove函数中分情况处理就好了,如下面一段代码:

void *memmove(void *dest, const void *src,int count)
{
	assert(dest);
	assert(src);
	char *dest1 = (char*)dest;
	char *src1 = (char*)src;
	char *p = dest1+count;
	char *q = src1 + count;
	if ((dest1 - src1)<count)
	{
		while (p>=dest1)
		{
			*p = *q;
			p--;
			q--;
		}
	}
	else
		while (count>0)
		{
			*dest1 = *src1;
			dest1++;
			src1++;
			count--;
		}
		return dest;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值