字符函数及内存函数的介绍及模拟实现

发布于:2022-12-09 ⋅ 阅读:(583) ⋅ 点赞:(0)

目录

一.字符函数的介绍及其模拟实现

1.strlen

2.strcpy

3.strcmp

4.strstr

5.strcat

 二.内存函数的介绍及其模拟实现

1.memcpy

2.memmove

 3.memcmp


一.字符函数的介绍及其模拟实现

1.strlen

介绍:strlen函数的官方声明如下,它的作用是获取字符串长度,它计算的是字符串'\0'之前的字符个数。

size_t strlen ( const char * str );

可以看到,strlen函数的参数是一个char类型的指针,它指向的是str数组首元素的地址,strlen函数的返回值是size_t类型,可能有人会疑惑size_t类型是什么?我们可以看看它的定义:

如图,size_t类型实际上是unsigned int类型,所以strlen函数返回的是一个无符号整形。 接下来我们来模拟实现strlen函数。

模拟实现:

size_t my_strlen(const char* str)
{
	int count = 0;//用来记录str内字符个数。
	while (*(str++))//利用while循环当str指向的不是'\0'时,count就自增1。
	{
		count++;
	}
	return count;
}

效果如图:

2.strcpy


介绍:strcpy的官方声明如下,它的作用是将A字符串拷贝到B字符串中,包括'\0'。

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

可以看到,strcpy函数的返回值是char*类型,它返回的是destination的地址。它的参数包含两个,一个是destination(目的地),一个是source(源头),将源头的字符串拷贝到目的地中。

模拟实现:

char* my_strcpy(char* destination, const char* source)
{
	assert(destination);//因为要保证传进来的不是空指针,所以要对两个指针进行断言。
	assert(source);//使用assert函数要引用头文件<assert.h>。
	char* str = destination;//记录destination指针初始位置。
	while (*(destination++) = *(source++))
	{
		;//通过while循环实现将source指向的字符串拷贝到destination中,
         //当source指向'\0'时循环结束。
	}
	return str;//返回destination指向的初始位置。
}

效果如图:

3.strcmp

介绍:官方声明如下,它的作用是将str1和str2进行比较。首字符如果相等,则继续比较下一对,直到字符不同或到达'\0'。str1和str2第一对不匹配的字符中,如果str1<str2,返回<0的数,反之则返回>0的数。如果str1与str2完全匹配则返回0.

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

 可以看到,函数的返回值是整形,两个参数都是字符指针。接下来我们将模拟实现这个函数。

模拟实现:

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);//断言
	while (*(str1) == *(str2))//只有第一对字符匹配才进入循环。
	{
		if (*(str1) == '\0'&&*(str2)=='\0')//两个字符串都为空字符串则直接返回0。
		{
			return 0;
		}
		str1++;//两个指针分别++指向下一个字符。
		str2++;
	}
//当str1和str2各自指向的字符不相同或者指向'\0'时跳出循环。
	return *(str1)-*(str2);//直接返回它们的差值就行。
}

效果如图:

4.strstr

介绍:官方声明如下:strstr的作用是定位字串,即在str1指向的字符串中查找是否存在str2指向的字符串内容,如果存在返回指向 str1中第一次出现 str2的指针,如果 str2不是str1的一部分,则返回空指针。

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

 可以看到,函数返回的是一个char*,两个参数都是字符指针。接下来对其模拟实现。

模拟实现:

char* my_strstr(const char* str1, const char* str2)
{
	char* s1 = str1;
	char* s2 = str2;
	char* ps = str1;//记录str1每次对比的初始位置。
	while (*ps)//ps没指向'\0',就进入循环
	{
		s1 = ps;
		s2 = str2;
		while (*s1 != '\0' && *s2 != '\0' && (*s1) == (*s2))
              //s1和s2不指向'\0',并且指向的内容相等就进入循环。
		{
			s1++;//进来后s1 s2都指向下一个位置。这样循环下去s2只有2中情况。
			s2++;//1.s2指向'\0'
                 //2.s2与s1不匹配。
		}
		if (*s2=='\0')//第一种情况。
		{
			return ps;
		}
		ps++;//第二种情况,不匹配就向后走一位再重新寻找是否存在相同的字符。
	}
	return NULL;//如果s1无论从哪个字符开始和s2比较都无法找到相同的字符串的话,
                //则说明s1中不存在s2,返回空指针就行。
}

5.strcat

介绍:

将源字符串的副本附加到目标字符串。目标中的终止空字符('\0')被源字符串的第一个字符覆盖,并且两者连接形成的新字符串的末尾包含一个空字符('\0'),最后返回目标字符串初始位置。

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

模拟实现:

​
char* my_strcat(char* destination, const char* source)
{
	assert(destination);//断言
	assert(source);
	char* str = destination;//记录初始位置。
	while (*(destination++))//通过循环让destination指向'\0'后一个字符。
	{
		;
	}
	destination--;//因为要覆盖'\0',所以让destination重新向后退一步,指向'\0'。
	while (*(destination++) = *(source++))
	{
		;//接下来通过while循环将source指向的字符串一个个接在destination指向的字符串后面。
	}
	return str;//返回destination的初始位置。

​}

效果如图:

 二.内存函数的介绍及其模拟实现

1.memcpy

介绍:将 num 个字节的值从 source 指向的位置直接复制到 destination 指向的内存块。

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

由声明可以看到,返回类型是void*,传进去的参数2个void*类型,一个size_t类型。

模拟实现:

void* my_memcpy(void* destination, const void* source, size_t num)
{
	void* str = destination;//记录destination初始位置
	while (num--)//拷贝num个字节
	{
		*(char*)destination = *(char*)source;//由于每次都只拷贝一个字节,
                                             //所以将其强制类型转化成char*后每次就只能访问到一            
                                             //个字节了。
		(char*)destination += 1;//拷贝了一个字节后,destination和source都指向下一个字节。
		(char*)source += 1;
	}
	return str;//返回destination初始位置。
}

效果如图:

2.memmove


介绍:将 num 个字节的值从 source 指向的位置复制到 destination 指向的内存块。允许目标字符串和源字符串重叠。

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

 这个函数和memcpy很相似,但这个函数允许source指向的内存块和destination指向的内存块重合。

模拟实现:

首先我们要知道,如果复制的是重合空间的内存块,那么一定会出现在复制过程中数据丢失的情况,所以我们要具体分析。

由图可知,当destination<source的时候,直接从前面一个一个复制过去就不会丢失数据,当destination>=source时则需要重内存块的最后面往前复制才不会丢失数据,如此我们就可以实现这个函数了。

void* my_memmove(void* destination, const void* source, size_t num)
{
	void* str = destination;//记录destination指向的初始位置
	assert(destination);//断言
	assert(source);
	if (destination < source)//第一种情况,从前面开始一个一个的复制。
	{
		while (num--)//因为要复制num个字节,所以循环num次。
		{
			*(char*)destination = *(char*)source;//赋值过去
			(char*)destination += 1;//指向位置后移
			(char*)source += 1;//后移
		}
	}
	else//第二种情况,从内存块后面开始向前面复制
	{
		while (num--)

		{
			*((char*)destination + num) = *((char*)source + num);//+num就会指向内存块的最后
		}
	}
	return str;//返回destination指向的初始位置。
}

效果如图:

 

 

 3.memcmp

介绍:内存比较函数,将 ptr1 指向的内存块的前 num 字节与 ptr2 指向的前 num 字节进行比较,如果它们都匹配则返回零,或者如果不匹配则返回一个不同于零的值,表示哪个更大(返回的值和strcmp相似)。 请注意,与 strcmp 不同的是,该函数在找到'\0'后不会停止比较。

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

由于这个函数和strcmp较为相似,所以具体实现直接看代码。

模拟实现:

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1);//断言
	assert(ptr2);
	if (!num)//num为0则返回0.
	{
		return 0;
	}
	while ((--num)&& *(char*)ptr1==*(char*)ptr2)//当num不为0,
                                                //且ptr1和ptr2首个指向的内存相同则进入循环。
	{
		(char*)ptr1 += 1;//指针位置后移。
		(char*)ptr2 += 1;//指针位置后移。
	}
	return *(char*)ptr1 - *(char*)ptr2;//返回差值。
}

效果如图:

 感谢你的观看!

本文含有隐藏内容,请 开通VIP 后查看