模拟字符串函数

目录

前言:

介绍:

1.

2.strlen

3.strcpy

4.strcat

5.strcmp

6.strstr

模拟实现:

1.my_strlen

计数器:

指针:

递归:

2.my_strcpy

3.my_strcat

4.my_strcmp

5.my_strstr

总结:


前言:

 本文主要以模拟实现库函数cstring中的部分字符串函数,包括:

“strlen”

“strcpy”

“strcat”

“strcmp”

“strstr”

介绍:

1.

模拟字符串函数_第1张图片

翻译过来,就是一个头文件,定义包含了一些使用C 字符串和数组的函数。

以上就是头文件string.h的定义。

2.strlen

模拟字符串函数_第2张图片

strlen简而言之就是统计字符串中‘\0’之前的元素个数。

相信大家已经对该函数有了一定了解,所以在此我们只是单单介绍,而重点在于模拟实现各个函数。

3.strcpy

模拟字符串函数_第3张图片

strcpy简而言之就是两个字符串的拷贝,将source里的字符数据拷贝到destination数组里,这里要注意的是,

拷贝也会把source数据里的‘\0’也拷贝进去。

必须要初始化两个数组。

并且保证destination足够大,且可以被修改。

切勿不可以使用char* destination = "abcd"这样子的常量字符串。

4.strcat

模拟字符串函数_第4张图片

strcat函数简而言之是字符串追加函数,是将source里的元素(包括‘\0’)追加到destination里‘\0’的位置往后,意思就是会将source首元素与destination里的‘\0’替换开始,往后追加。

5.strcmp

模拟字符串函数_第5张图片

strcmp简而言之就是字符串比较函数,当str1中字符小于str2中的字符就返回-1,相等返回0,大于返回1。

模拟字符串函数_第6张图片

要注意的是,这里我们是比较他们的ASCII码值。

6.strstr

模拟字符串函数_第7张图片

strstr简而言之就是字符串查找函数,看看str1是否含有str2中的字符串,当存在时,就返回包含str2字符串加上后续内容的str1字符串。

以上就是我们将要模拟实现的字符串函数内容。

模拟实现:

1.my_strlen

我们在实现my_strlen函数可以使用三种方法:

分别是,“计数器”,“指针”,“递归”

计数器:

代码如下:

int my_strlen(const char* arr)
{
	int count = 0;
	while (*arr++)
	{
		count++;
	}
	return count;
}

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", my_strlen(arr));
	return 0;
}

计数器方法为最基础的内容,相信大家仅仅看代码就可以看明白

最终输出结果为

6

指针:

代码如下:

int my_strlen(const char* arr)
{
	char* ret = arr;
	while (*ret++)
	{
		;
	}
	return ret - arr - 1;
}

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", my_strlen(arr));
	return 0;
}

对于使用指针的方法解决,我们的具体操作是再创建一个指针ret,使ret对数组进行遍历操作,当ret指向‘\0’时,就停止,这样ret指向的‘\0’与首元素地址相差的值就是字符串元素个数了。

递归:

int my_strlen(const char* arr)
{
	if (*arr == '\0')
	{
		return 0;
	}
	return 1 + my_strlen(arr + 1);
}

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", my_strlen(arr));
	return 0;
}

我们在学习递归的时候就会涉及该代码,在这里我不多进行赘述,看看代码就可以看懂。

2.my_strcpy

代码如下:

#include
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char dest[] = "XXXXXXXXXXXXX";
	char src[] = "hello";
	printf("%s\n", my_strcpy(dest, src));
	return 0;
}

在这里我们引入拓展了一个新知识点,assert

模拟字符串函数_第8张图片

翻译过来再概括一下,就是assert为断言函数,它可以在调试的时候捕捉程序错误,我们目前只需知道这些就足够了,加上这一句可以使得代码风格更加健壮。

这里要注意的是,我们需要创建一个临时ret指针来帮助我们进行遍历,如果仅仅是单单移动dest指针,那这样经过后置++后指向的地址就不能恢复原状了。

输出结果为:

模拟字符串函数_第9张图片

3.my_strcat

代码如下:

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;

	while (*dest != '\0')
	{
		dest++;
	}

	/*while (*dest++)
	{
		;
	}*/ //不能写成这样,这样则会跳过‘\0’到下一个元素

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

	return ret;
}

int main()
{
	char dest[20] = "abc";
	char src[20] = "def";
	printf("%s\n", my_strcat(dest, src));
	return 0;
}

对于该函数的模拟,与strcpy相似,创建一个临时指针来进行遍历,但是这里我们才去的方法不一样的是:

模拟字符串函数_第10张图片

如果用此while循环遍历时,当dest指向‘\0’时还会再进行一次++操作,这样我们就是将src中的元素追加到‘\0’后面了,即如图所示:

模拟字符串函数_第11张图片

模拟字符串函数_第12张图片

那这样存放数据就会变成下图:

模拟字符串函数_第13张图片

这样当我们去访问dest时,打印遇到‘\0’就会停止了。

输出结果为:

模拟字符串函数_第14张图片

4.my_strcmp

int my_strcmp(const char* dest, const char* src)
{
	while ((*dest != '\0') && (*src != '\0'))
	{
		if (*dest < *src)
		{
			return -1;
		}
		else if (*dest>*src)
		{
			return 1;
		}
		else
		{
			++dest;
			++src;
		}
	}
	if (*dest < *src)
	{
		return -1;
	}
	else if (*dest>*src)
	{
		return 1;
	}
	return 0;

}
int main()
{
	char dest[] = "abcd";
	char src[] = "abd";

	printf("%d\n", my_strcmp(dest, src));
	return 0;
}

本代码没有过多需要解释的,多看几遍代码就可以看懂,我们把重点放在下述的strstr中。

输出结果为:

模拟字符串函数_第15张图片

5.my_strstr

#include
const char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	if (*str2 == '\0'){ return str1; }
	const char* p = str1;
	const char* s1 = NULL;
	const char* s2 = NULL;
	while (*p)
	{
		s1 = p;
		s2 = str2;
		while (*s1 == *s2 && *s1 && *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0'){ return p; }
		p++;
	}
	return NULL;
}

int main()
{
	char str1[] = "abbcd";
	char str2[] = "abc";
	const char* ret = my_strstr(str1, str2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret);
	}
	return 0;
}

对于该函数的实现,我们用画图的方式来讲解容易理解些。

这里提前讲解下s1 、s2 、p分别代表什么。

s1为遍历str1的指针

s2为遍历str2的指针

p为记录开始匹配位置的指针

具体实现如图:
模拟字符串函数_第16张图片

以上是我们第一次初始化的具体图示,

接下来我们进入while(*p)循环中

如图:

模拟字符串函数_第17张图片

此时s1指向的位置与s2指向的位置不一致,所以p++。

这时候s1也进行++,

模拟字符串函数_第18张图片

这是进入第二个while循环里,发现满足*s1 == *s2,所以s1和s2各自++,

模拟字符串函数_第19张图片

此时不满足第二个while循环,所以跳出循环,p再++。

s2回到首元素地址处,

模拟字符串函数_第20张图片

再次进入第二个循环,又发现*s1 == *s2,

模拟字符串函数_第21张图片

又发现相等,继续循环,直到如图所示

模拟字符串函数_第22张图片

此时*s2 == ‘\0’,return p指向的位置。

这样输出结果就是bcd。

如图:

模拟字符串函数_第23张图片以上就是strstr的模拟实现,下来可以动手画一画图。

总结:

以上代码是在string.h中模拟实现部分字符串函数,后续我会继续补充更多的内容。

记住

“坐而言不如起而行”

“Action spear louder than words”

具体的代码可以参考我的Gitee:

The_character_function_CSDN/The_character_function_CSDN/test.c · 无双/test_c_with_X1 - Gitee.com

你可能感兴趣的:(c语言,笔记,经验分享)