• C/C++字符函数和字符串函数详解————内存函数详解与模拟


    个人主页点我进入主页

    专栏分类:C语言初阶      C语言程序设计————KTV       C语言小游戏     C语言进阶

    C语言刷题

    欢迎大家点赞,评论,收藏。

    一起努力,一起奔赴大厂。

    目录

    1.前言

    2 .memcpy函数

    3.memmove函数

    4.memset函数

     5.memcmp函数


    1.前言

               前面学习了关于长度受限制的字符串函数和长度不受限制的字符串函数,其中strcmp对应strncmp函数,strcpy函数对应strncpy函数,strcat函数对应strncat函数,今天我们主要了解的是四个内存函数他们分别是memcpy函数,memmove函数,memset函数,memcmp函数。其中memcpy函数和strcpy函数的功能类似,memcmp函数和strcmp函数类似,接下来就让我们感受一下这些函数的魅力吧。

    2 .memcpy函数

            对于memcpy函数,有很多人都是第一次接触到,我们进入cplusplus网站cplusplus进行查看memcpy函数的参数。

            我们看到函数的参数是void * destination, const void * source, size_t num,对于参数我们需要知道这个函数是有什么功能,它主要就是对任何类型的数据进行拷贝,所以destination和source都是void*类型,因为void*类型可任盛放任何类型的指针,其中destination是指向目标的指针,source是指向来源的指针,num是想要拷贝几个字节,接下来进行代码演示,代码如下:

    1. #include
    2. #include
    3. int main()
    4. {
    5. int arr1[10] = { 0 };
    6. int arr2[5] = { 2,3,4,5,6 };
    7. memcpy(arr1, arr2, 20);
    8. int i;
    9. for (i = 0; i < 10; i++)
    10. {
    11. printf("%d ", arr1[i]);
    12. }
    13. return 0;
    14. }

     我么运行代码,结果如下:

    接下来进行函数的模拟

    1. #include
    2. #include
    3. void* my_memcpy(void* str1, const void* str2, size_t num)
    4. {
    5. char* p = (char*)str1;
    6. while (num--)
    7. {
    8. *(char*)str1 = *(char*)str2;
    9. str1 = (char*)str1 + 1;
    10. str2 = (char*)str2 + 1;
    11. }
    12. return p;
    13. }
    14. int main()
    15. {
    16. int arr1[10] = { 0 };
    17. int arr2[5] = { 2,3,4,5,6 };
    18. my_memcpy(arr1, arr2, 20);
    19. int i;
    20. for (i = 0; i < 10; i++)
    21. {
    22. printf("%d ", arr1[i]);
    23. }
    24. return 0;
    25. }

            在这里我们需要进行强制转化,转化为char*类型然后一个字节一个字节进行修改,但是这个函数有一定的局限性,当它的目的指针和来源指针指向同一数据且有有重叠部分时函数会出现与预期不同的结果,我们可以简单画一下:

    当我们想要把str1拷贝到str2上时当我们拷贝了前三个数据,str1和原来的str2重合时

             想要再次进行修改就会出现 重复拷贝,根据c语言的标准memcpy函数是对来自不同数据的进行拷贝,但是对于来自同一数组的需要用另外的一个函数,此函数就是memmove函数接下来我们介绍memmove函数。

    3.memmove函数

            我们同样进入cplusplus网站查看memmove函数的参数,以及功能

               我们看到函数的参数是void * destination, const void * source, size_t num,memmove函数的功能和memcpy函数的功能类似 ,只是memmove是对于来自同一数组的数据进行拷贝,destination和source都是void*类型,因为void*类型可任盛放任何类型的指针,其中destination是指向目标的指针,source是指向来源的指针,num是想要拷贝几个字节,接下来进行代码演示,代码如下:

    1. #include
    2. #include
    3. int main()
    4. {
    5. int arr[10] = { 0,1,2,3,4,5,6,7,8,9};
    6. memmove(arr, arr + 3, 20);
    7. int i;
    8. for (i = 0; i < 10; i++)
    9. {
    10. printf("%d ", arr[i]);
    11. }
    12. return 0;
    13. }

    运行结果如下:

    接下啦我们进行memmove函数的模拟实现,代码如下:

    1. #include
    2. #include
    3. #include
    4. void my_memmove(void* str1, const void* str2, size_t sz)
    5. {
    6. assert(str1 && str2);
    7. if (str1 < str2)
    8. {
    9. while (sz--)
    10. {
    11. *(char*)str1 = *(char*)str2;
    12. str1 = (char*)str1 + 1;
    13. str2 = (char*)str2 + 1;
    14. }
    15. }
    16. else
    17. {
    18. while (sz--)
    19. {
    20. *((char*)str1 + sz) = *((char*)str2 + sz);
    21. }
    22. }
    23. }
    24. int main()
    25. {
    26. int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
    27. my_memmove(arr+3, arr , 20);
    28. int i;
    29. for (i = 0; i < 10; i++)
    30. {
    31. printf("%d ", arr[i]);
    32. }
    33. return 0;
    34. }

     在这里我们需要看两种情况,第一种是str1在str2前面

    这种情况我们只需从前往后进行赋值即可。对于第二种

     str1在str2的后面我们不能从前向后进行拷贝,否则就会出现重复赋值,出现错误,这时我们只需要从后往前进行赋值就可以解决。

    4.memset函数

             我们进入cplusplus网站进行查阅

            memset函数是对数据进行初始化的函数,这个数据可以是任意类型,但是字符串比较适用,ptr是指向想要修改的位置,value是想要修改为什么值,num是修改几个字节,我们直接进入代码演示,代码如下:

    1. #include
    2. #include
    3. int main()
    4. {
    5. char arr[] = "abcdefg";
    6. memset(arr, 'x', 4);
    7. printf("%s", arr);
    8. return 0;
    9. }

    运行结果如下:

    接下来进入我们模拟实现,代码如下:

    1. #include
    2. #include
    3. #include
    4. void* my_memset(void* str, int vaul, size_t sz)
    5. {
    6. assert(str);
    7. char* p = (char*)str;
    8. while (sz--)
    9. {
    10. *(char*)str = vaul;
    11. str = (char*)str + 1;
    12. }
    13. return p;
    14. }
    15. int main()
    16. {
    17. char arr[] = "abcdefg";
    18. my_memset(arr, 'x', 4);
    19. printf("%s", arr);
    20. return 0;
    21. }

     5.memcmp函数

            我们进入cplusplus网站查看函数的参数 

            memcmp函数的功能就是比较数据的大小,其中num是需要比较的数据的字节数,功能和strncmp类似,我们直接上代码:

     

    1. #include
    2. #include
    3. int main()
    4. {
    5. int arr[5] = { 0,1,2,3,4 };
    6. int arr1[5] = { 0 };
    7. int ret = memcmp(arr, arr1, 5);
    8. printf("%d", ret);
    9. return 0;
    10. }

    我们可以理解为 

    前4个字节相同,第五个字节str1大于str2故返回1。运行结果如下;

     

    接下来进行memcmp函数的模拟实现,代码如下:

    1. #include
    2. #include
    3. #include
    4. int my_memcmp(const void* str1, const void* str2, size_t sz)
    5. {
    6. assert(str1 && str2);
    7. int i;
    8. for (i = 0; i < sz; i++)
    9. {
    10. if (*(char*)str1 >*(char*)str2)
    11. {
    12. return 1;
    13. }
    14. else if (*(char*)str1 < *(char*)str2)
    15. {
    16. return -1;
    17. }
    18. str1 = (char*)str1 + 1;
    19. str2 = (char*)str2 + 1;
    20. }
    21. return 0;
    22. }
    23. int main()
    24. {
    25. int arr[5] = { 0,1,2,3,4 };
    26. int arr1[5] = { 0 };
    27. int ret = my_memcmp(arr, arr1, 5);
    28. printf("%d", ret);
    29. return 0;
    30. }

    今天的内容就结束了,希望大家可以学到一些东西。

  • 相关阅读:
    Java中Date实现比较大小
    Django——数据库
    稳定智能的在线考试系统
    OSI与TCP/IP与的体系结构的比较
    Docker应用下滑、近七成开发者有安全疑虑,中国云原生用户调查报告来了
    css如何实现页面布局与五种实现方式
    vue3 父子组件间的通信
    Django系列2-Django安装及创建项目
    排查disabled问题之谷歌新版本特性
    合同法重点知识总结
  • 原文地址:https://blog.csdn.net/Infernal_Puppet/article/details/133560166