常用字符串函数的模拟实现

目录

strlen的模拟实现

strcpy的模拟实现

strcat的模拟实现

strcmp的模拟实现

strstr的模拟实现

memcpy的模拟实现

memmove的模拟实现


 

strlen的模拟实现

size_t strlen (const char* str);

strlen该函数是统计字符串的长度的

方法1:计数器count

利用临时变量count来统计字符的个数。

int my_strlen(const char* str)
{
	int count = 0;
	assert(str);//断言指针的有效性
	while (*str++)//当str不为'\0'执行
		count++;
	return count;
}

方法2:递归(不创建临时变量)

这里没有使用任何临时变量,通过一层一层的递归来实现的。

//abcd
//1+bcd
//1+1+cd
//1+1+1+d
//1+1+1+1
int my_strlen(const char* str)
{
	if (*str)
		return 1 + my_strlen(str + 1);
	return 0;
}

方法3:指针-指针 

指针-指针的结果是中间元素的个数,所以我们通过2个指针,一个指向首元素,一个指向'\0',然后高地址减低地址就是结果了

int my_strlen(const char* str)
{
	const char* end = str;
	while (*end++);
	return (int)(--end - str);
}

strcpy的模拟实现

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

strcpy是字符串拷贝函数,将source拷贝到destination中

模拟实现strcpy时需要注意以下几点:

①目标空间必须足够大

②目标空间必须是可以修改的(不能是常量字符串)

③源字符串必须以'\0'结束

④它会把源字符串中的'\0'也拷贝到目标空间

char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);//断言指针的有效性
	while (*dest++ = *src++);//将*src赋值给*dest后,判断这个值是否为0,然后再src++,dest++
	return ret;
}

int main()
{
	char str1[20] = "abcdef";
	char str2[] = "Hello World";
	//将str2拷贝到str1中
    //预期效果为 Hello World
	char* ret = my_strcpy(str1, str2);
	printf("%s\n", ret);
	return 0;
}

strcat的模拟实现

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

strcat是字符串的追加函数,将source追加到destination后面

模拟实现strcat需要注意以下几点:

①源字符串和目标字符串都必须是以'\0'结束

②目标空间必须足够大

③目标空间必须可修改

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);//断言指针的有效性
	while (*dest)//找到dest中的'\0'
		dest++;
	while (*dest++ = *src++);//将src中的内容赋给dest(包括'\0')
	return ret;
}

int main()
{
	char str1[20] = "Hello";
	char str2[] = "World!";
	//将字符串str2追加到str1的后面
    //预期效果为 HelloWorld!
	char* ret = my_strcat(str1, str2);
	printf("%s\n", ret);
	return 0;
}

strcmp的模拟实现

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

strcmp是字符串的比较函数

如果str1 > str2,返回一个大于0的数

如果str1 < str2,返回一个小于0的数

如果str1 = str2,返回0

【实际上,在VS中大于0的数就被固定为1,小于0的数就被固定为-1了】

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);//断言指针的有效性
	while (*str1 == *str2)//*str1和*str2相等进入循环,否则直接return
	{
		if (!*str1)//如果*str1和*str2都指向了'\0',那么它们就相等了
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}

int main()
{
	char str1[] = "abcde";
	char str2[] = "abcdf";
	//比较str1和str2的大小
	int ret = my_strcmp(str1, str2);
	printf("%d\n", ret);
	return 0;
}

strstr的模拟实现

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

strstr是一个找子串的函数,返回值是找到的第一个子串的地址

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);//断言指针的有效性
	char* s1 = (char*)str1;//移动s1和s2指针来进行比较
	char* s2 = (char*)str2;
	char* cur = s1;//cur指针是记录当前从哪个字符开始比较的
	while (*cur)
	{
		while (*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (!*s2)//s2如果访问到了'\0',那么说明已经找到了子串了
			return cur;//返回记录这一子串的首地址
		cur++;
		s1 = cur;
		s2 = (char*)str2;//重置s2
	}
	return NULL;//如果找不到,返回NULL
}

int main()
{
	char str1[] = "ABBCDEF";
	char str2[] = "BCD";
	//从str1中找str2
	char* ret = my_strstr(str1, str2);
	printf("%s\n", ret);
	return 0;
}

memcpy的模拟实现

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

memcpy是内存拷贝函数,可以拷贝任意类型的数据。

模拟实现memcpy需要注意以下几点:

①memcpy与strcpy不同,它遇到'\0'不会停下来

②memcpy是从source的起始位置向后复制num个字节到destination中

void* my_memcpy(void* dest, const void* src, size_t n)
{
	void* ret = dest;
	assert(dest && src);//断言指针的有效性
	while (n--)//记录拷贝了多少个字节
	{
		*(char*)dest = *(char*)src;//以char为单位,因为char是1个字节
		++(char*)dest;
		++(char*)src;
	}
	return ret;
}

int main()
{
	int arr1[] = { 1,3,5,7,9};
	int arr2[] = { 2,4,6 };
	//将arr1中的前12个字节设置为arr2前12个字节的内容
    //预期效果为 2 4 6 7 9
	my_memcpy(arr1, arr2, 12);
	int i = 0;
	for (i = 0;i < 5;i++)
		printf("%d ", arr1[i]);
	return 0;
}

memmove的模拟实现

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

memmove和memcpy都是拷贝任意类型的数据的

memmove与memcpy不同的是它可以处理源内存块与目标内存块重叠的情况。

void* memmove(void* dest, const void* src, size_t n)
{
	void* ret = dest;
	assert(dest && src);//断言指针的有效性
	if (dest > src)
	{
		while (n--)//从后--->前 拷贝
		{
			*((char*)dest + n) = *((char*)src + n);//从后向前每个字节每个字节的拷贝
		}
	}
	else//dest < src
	{
		while (n--)//从前--->后 拷贝
		{
			*(char*)dest = *(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	}
	return ret;
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//将从arr开始的前20个字节拷贝到arr+2开始的前20个字节中
	memmove(arr + 2, arr, 20);
	int i = 0;
	for (i = 0;i < 10;i++)
		printf("%d ", arr[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_51696091/article/details/113360612