目录
本文主要以模拟实现库函数cstring中的部分字符串函数,包括:
“strlen”
“strcpy”
“strcat”
“strcmp”
“strstr”

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

strlen简而言之就是统计字符串中‘\0’之前的元素个数。
相信大家已经对该函数有了一定了解,所以在此我们只是单单介绍,而重点在于模拟实现各个函数。

strcpy简而言之就是两个字符串的拷贝,将source里的字符数据拷贝到destination数组里,这里要注意的是,
拷贝也会把source数据里的‘\0’也拷贝进去。
必须要初始化两个数组。
并且保证destination足够大,且可以被修改。
切勿不可以使用char* destination = "abcd"这样子的常量字符串。

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

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

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

strstr简而言之就是字符串查找函数,看看str1是否含有str2中的字符串,当存在时,就返回包含str2字符串加上后续内容的str1字符串。
以上就是我们将要模拟实现的字符串函数内容。
我们在实现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;
- }
我们在学习递归的时候就会涉及该代码,在这里我不多进行赘述,看看代码就可以看懂。
代码如下:
- #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

翻译过来再概括一下,就是assert为断言函数,它可以在调试的时候捕捉程序错误,我们目前只需知道这些就足够了,加上这一句可以使得代码风格更加健壮。
这里要注意的是,我们需要创建一个临时ret指针来帮助我们进行遍历,如果仅仅是单单移动dest指针,那这样经过后置++后指向的地址就不能恢复原状了。
输出结果为:

代码如下:
- 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相似,创建一个临时指针来进行遍历,但是这里我们才去的方法不一样的是:

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


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

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

- 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中。
输出结果为:

- #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为记录开始匹配位置的指针
具体实现如图:
以上是我们第一次初始化的具体图示,
接下来我们进入while(*p)循环中
如图:

此时s1指向的位置与s2指向的位置不一致,所以p++。
这时候s1也进行++,

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

此时不满足第二个while循环,所以跳出循环,p再++。
s2回到首元素地址处,

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

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

此时*s2 == ‘\0’,return p指向的位置。
这样输出结果就是bcd。
如图:
以上就是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