• 模拟字符串函数


    目录

    前言:

    介绍:

    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.

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

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

    2.strlen

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

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

    3.strcpy

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

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

    必须要初始化两个数组。

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

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

    4.strcat

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

    5.strcmp

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

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

    6.strstr

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

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

    模拟实现:

    1.my_strlen

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

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

    计数器:

    代码如下:

    1. int my_strlen(const char* arr)
    2. {
    3. int count = 0;
    4. while (*arr++)
    5. {
    6. count++;
    7. }
    8. return count;
    9. }
    10. int main()
    11. {
    12. char arr[] = "abcdef";
    13. printf("%d\n", my_strlen(arr));
    14. return 0;
    15. }

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

    最终输出结果为

    6

    指针:

    代码如下:

    1. int my_strlen(const char* arr)
    2. {
    3. char* ret = arr;
    4. while (*ret++)
    5. {
    6. ;
    7. }
    8. return ret - arr - 1;
    9. }
    10. int main()
    11. {
    12. char arr[] = "abcdef";
    13. printf("%d\n", my_strlen(arr));
    14. return 0;
    15. }

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

    递归:

    1. int my_strlen(const char* arr)
    2. {
    3. if (*arr == '\0')
    4. {
    5. return 0;
    6. }
    7. return 1 + my_strlen(arr + 1);
    8. }
    9. int main()
    10. {
    11. char arr[] = "abcdef";
    12. printf("%d\n", my_strlen(arr));
    13. return 0;
    14. }

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

    2.my_strcpy

    代码如下:

    1. #include
    2. char* my_strcpy(char* dest, const char* src)
    3. {
    4. assert(dest && src);
    5. char* ret = dest;
    6. while (*dest++ = *src++)
    7. {
    8. ;
    9. }
    10. return ret;
    11. }
    12. int main()
    13. {
    14. char dest[] = "XXXXXXXXXXXXX";
    15. char src[] = "hello";
    16. printf("%s\n", my_strcpy(dest, src));
    17. return 0;
    18. }

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

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

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

    输出结果为:

    3.my_strcat

    代码如下:

    1. char* my_strcat(char* dest, const char* src)
    2. {
    3. char* ret = dest;
    4. while (*dest != '\0')
    5. {
    6. dest++;
    7. }
    8. /*while (*dest++)
    9. {
    10. ;
    11. }*/ //不能写成这样,这样则会跳过‘\0’到下一个元素
    12. while (*dest++ = *src++)
    13. {
    14. ;
    15. }
    16. *dest = *src;
    17. return ret;
    18. }
    19. int main()
    20. {
    21. char dest[20] = "abc";
    22. char src[20] = "def";
    23. printf("%s\n", my_strcat(dest, src));
    24. return 0;
    25. }

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

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

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

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

    输出结果为:

    4.my_strcmp

    1. int my_strcmp(const char* dest, const char* src)
    2. {
    3. while ((*dest != '\0') && (*src != '\0'))
    4. {
    5. if (*dest < *src)
    6. {
    7. return -1;
    8. }
    9. else if (*dest>*src)
    10. {
    11. return 1;
    12. }
    13. else
    14. {
    15. ++dest;
    16. ++src;
    17. }
    18. }
    19. if (*dest < *src)
    20. {
    21. return -1;
    22. }
    23. else if (*dest>*src)
    24. {
    25. return 1;
    26. }
    27. return 0;
    28. }
    29. int main()
    30. {
    31. char dest[] = "abcd";
    32. char src[] = "abd";
    33. printf("%d\n", my_strcmp(dest, src));
    34. return 0;
    35. }

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

    输出结果为:

    5.my_strstr

    1. #include
    2. const char* my_strstr(const char* str1, const char* str2)
    3. {
    4. assert(str1 && str2);
    5. if (*str2 == '\0'){ return str1; }
    6. const char* p = str1;
    7. const char* s1 = NULL;
    8. const char* s2 = NULL;
    9. while (*p)
    10. {
    11. s1 = p;
    12. s2 = str2;
    13. while (*s1 == *s2 && *s1 && *s2)
    14. {
    15. s1++;
    16. s2++;
    17. }
    18. if (*s2 == '\0'){ return p; }
    19. p++;
    20. }
    21. return NULL;
    22. }
    23. int main()
    24. {
    25. char str1[] = "abbcd";
    26. char str2[] = "abc";
    27. const char* ret = my_strstr(str1, str2);
    28. if (ret == NULL)
    29. {
    30. printf("找不到\n");
    31. }
    32. else
    33. {
    34. printf("%s\n", ret);
    35. }
    36. return 0;
    37. }

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

    这里提前讲解下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

  • 相关阅读:
    SSL OV证书和DV、EV证书的区别
    《Unity Shader 入门精要》笔记04
    【VUEX】最好用的传参方式--Vuex的详解
    sql基础
    CMakeLists.txt简单项目模板
    21天打卡挑战学习MySQL——《MySQL表管理》第二周 第五篇
    UVA10410 树重建 Tree Reconstruction
    【单例模式】饿汉式,懒汉式?JAVA如何实现单例?线程安全吗?
    (经典dp) hdu 递推求解专题练习
    对Promise的理解
  • 原文地址:https://blog.csdn.net/weixin_72917087/article/details/133034917