关于C库函数的一些模拟实现以及讲解思考

简介: 关于C库函数的一些模拟实现以及讲解思考

@[TOC]

memcpy函数

memcpy函数分析

首先这个函数的功能是用来进行内存拷贝的,仿照与strcpy,那么关于它的定义有如下解释

在这里插入图片描述
从图中可以看出,函数拥有三个参数,destination(目的地),source(来源于哪),num(需要几个字节),而函数的功能如下:Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.

即将源头的内容拷贝到目的地中,拷贝num个==字节==

在这里回顾void*

void*是一个万能指针,它可以接收任意类型的指针,但相应的这是有代价的,你不能通过它直接取出里面的内容,需要将它强制转化为某种类型的指针,才能将它取出


而在这个函数中,由于我们不知道具体要拷贝什么类型的函数,于是我们就直接将这个指针类型设置为void*

那么有了上面的分析,模拟实现如下

memcpy模拟实现

//模拟实现memcpy
#include <stdio.h>
#include <string.h>

void* my_memcpy(void* arr2, void* arr1, size_t size)
{
   
   
    while (size--)
    {
   
   
        *(char*)arr2 = *(char*)arr1;
        (char*)arr2 = (char*)arr2 + 1;
        (char*)arr1 = (char*)arr1 + 1;
    }
}

int main()
{
   
   
    int arr1[10] = {
   
    1,2,3,4,5,6,7,8,9 };
    int arr2[20] = {
   
    0 };
    //memcpy(arr2, arr1, 16);
    my_memcpy(arr2, arr1, 16);
    for (int i = 0; i < 10; i++)
    {
   
   
        printf("%d ", arr2[i]);
    }
    return 0;
}

memmove函数

memmove函数分析

其实memmove函数和memcpy函数功能基本类似,在有些编译器上它们的功能甚至会被手动优化,那么有什么区别?

我们来看下面的例子,输出结果是多少?

void* my_memcpy(void* arr2, void* arr1, size_t size)
{
   
   
    void* ret = arr2;
    while (size--)
    {
   
   
        *(char*)arr2 = *(char*)arr1;
        (char*)arr2 = (char*)arr2 + 1;
        (char*)arr1 = (char*)arr1 + 1;
    }
    return ret;
}

int main()
{
   
   
    int arr1[10] = {
   
    1,2,3,4,5,6,7,8,9 };
    int arr2[10] = {
   
    0 };
    //my_memmove(arr1+2, arr1, 16);
    my_memcpy(arr1 + 2, arr1, 16);
    for (int i = 0; i < 10; i++)
    {
   
   
        printf("%d ", arr1[i]);
    }
    return 0;
}

输出结果如下
在这里插入图片描述

==为什么?==

这段代码的目的是把arr的数据复制到arr+2的地方去,总共复制16个字节的内容,图示如下:
在这里插入图片描述
问题就在于3和4上,这两个元素是有重叠部分的,在这个部分内的元素会发生重叠,导致拷贝出错,出错原因如下:
在这里插入图片描述
如下图,当内存中开始取代时,重叠部分的区域会来回取代,这样就导致了刚才输出的异常,那么解决方法就是现在的这个memmove函数

这个函数的功能强大在于,它可以根据dest和reso的位置确定是从前往后拷贝还是从后往前拷贝,对于上面这个情况,如果我们采取的是从后向前拷贝,模式图如下:

在这里插入图片描述
在这种模式下就可以做到拷贝,那么总结一下就得到了下面的函数实现

memmove模拟实现

void* my_memmove(void* dest, void* reso, size_t size)
{
   
   
    void* ret = dest;
    if (reso > dest)
    {
   
   
        while (size--)
        {
   
   
            *(char*)dest = *(char*)reso;
            (char*)dest = (char*)dest + 1;
            (char*)reso = (char*)reso + 1;
        }
    }
    else
    {
   
   
        while (size--)
        {
   
   
            *((char*)dest + size) = *((char*)reso + size);
        }
    }
    return ret;
}

void* my_memcpy(void* arr2, void* arr1, size_t size)
{
   
   
    void* ret = arr2;
    while (size--)
    {
   
   
        *(char*)arr2 = *(char*)arr1;
        (char*)arr2 = (char*)arr2 + 1;
        (char*)arr1 = (char*)arr1 + 1;
    }
    return ret;
}

int main()
{
   
   
    int arr1[10] = {
   
    1,2,3,4,5,6,7,8,9 };
    int arr2[10] = {
   
    0 };
    my_memmove(arr1+2, arr1, 16);
    //my_memcpy(arr1 + 2, arr1, 16);
    for (int i = 0; i < 10; i++)
    {
   
   
        printf("%d ", arr1[i]);
    }
    return 0;
}

从这个函数体中能看出,实际上是分为两种情况,一种情况是如果源头在目标的前面,就从前向后拷贝,如果在后面就从后向前拷贝

用这种很巧妙的方式解决了这个问题

strstr函数

strstr函数分析

==char strstr(const char haystack, const char *needle)==
在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 '\0'。

这是一个查找字符串的函数,在一段字符串中查找指定的字符串,如果找到了就返回地址

strstr函数模拟实现

//strstr模拟实现
#include <stdio.h>

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

int main()
{
   
   
    char str1[] = {
   
    "abcde" };
    char str2[] = {
   
    "bcd" };
    printf("%s\n", my_strstr(str1, str2));
    return 0;
}

strlen函数

函数分析

字符串函数中应用最广的函数之一,主要作用是寻找字符串中的\0,并记录在这之前有多少个字符,用来计算==字符串==的长度

strlen函数模拟实现

下面展示了三种strlen函数的模拟实现方式,指针,递归,和计数器

//strlen函数模拟
#include <stdio.h>
#include <string.h>

//计数器
size_t my_strlen1(const char* arrr)
{
   
   
    int ret = 0;
    while (*arrr != '\0')
    {
   
   
        ret++;
        arrr++;
    }
    return ret;
}

//指针-指针
size_t my_strlen2(const char* arr)
{
   
   
    int ret = 0;
    const char* p = arr;
    while (*arr != '\0')
    {
   
   
        arr++;
    }
    ret =(int)(arr - p);
    return ret;
}

//递归
size_t my_strlen3(const char* str)
{
   
   
    if (*str == '\0')
    {
   
   
        return 0;
    }
    else
    {
   
   
        return 1 + my_strlen3(str + 1);
    }
}

int main()
{
   
   
    char arr[] = "abcd";
    int len1 = (int) my_strlen1(arr);
    int len2 = (int)my_strlen2(arr);
    int len3 = (int)my_strlen3(arr);
    printf("%d\n", len1);
    printf("%d\n", len2);
    printf("%d\n", len3);
    return 0;
}

strcpy函数

strcpy函数分析

strcpy函数又叫做字符串拷贝函数,运用场景通常是需要把一个字符串赋予给另外一个字符串时,由于语法限定不可以使用==arr1=arr2==这种语句用来赋值,于是诞生了字符串复制函数。


字符串函数通常都和\0有关,这个函数也不例外,这个函数的原理就是找到字符串中的\0并把它前面的内容复制到另外一个字符串中

strcpy函数模拟实现

//strcpy函数模拟
#include <stdio.h>

void my_strcpy1(char* arr2, const char* arr1)
{
   
   
    do
    {
   
   
        *arr2 = *arr1;
        arr2++;
        arr1++;
    } while (*arr1 != '\0');
}

char* my_strcpy2(char* str2, const char* str1)
{
   
   
    char* ret = str1;
    while (*str2++ = *str1++);
    return ret;
}

int main()
{
   
   
    char arr1[] = {
   
    "abcdef" };
    char arr2[10] = {
   
    0 };
    char arr3[10] = {
   
    0 };
    my_strcpy1(arr2, arr1);
    my_strcpy2(arr3, arr1);
    printf("%s\n", arr1);
    printf("%s\n", arr2);
    printf("%s\n", arr3);
    printf("%s\n", my_strcpy2(arr3, arr1));
    return 0;
}

strcat函数

strcat函数分析

strcat函数也叫做字符串追加函数,在指定的字符串后追加要追加的部分

strcat函数模拟实现

//strcat函数模拟
#include <stdio.h>
#include <string.h>

char* my_strcat(char* arr1, char* arr2)
{
   
   
    char* ret = arr1;
    while (*arr1 != '\0')
    {
   
   
        arr1++;
    }
    while (*arr2 != '\0')
    {
   
   
        *arr1 = *arr2;
        arr2++;
        arr1++;
    }
    return ret;
}

int main()
{
   
   
    char arr1[20] = "abcdef";
    char arr2[] = "ghi";
    printf("%s\n", my_strcat(arr1, arr2));
    return 0;
}

strcmp函数

strcmp函数分析

这个函数也叫做字符串比较函数,给定两个字符串进行比较,比较的是字符串的ASCII码值,如果相等进行下一个,直到必出大小或遇到\0


如果A字符串大于B字符串,返回一个大于0的数,小于返回一个小于0的数,如果相等则返回0

strcmp函数模拟实现

//strcmp函数模拟
#include <stdio.h>
#include <string.h>

int my_strcmp(char* arr1, char* arr2)
{
   
   
    int ret = 0;
    while (*arr1 != '\0' && *arr2 != '\0')
    {
   
   
        if (*arr1 > *arr2)
        {
   
   
            ret = 1;
            break;
        }
        else if (*arr1 < *arr2)
        {
   
   
            ret = -1;
            break;
        }
        else
        {
   
   
            arr1++;
            arr2++;
        }
    }
    return ret;
}

int main()
{
   
   
    char arr1[] = {
   
    "abcde" };
    char arr2[] = {
   
    "abcde\0fg" };
    int len = my_strcmp(arr1, arr2);
    printf("%d", len);
    return 0;
}
相关文章
|
12月前
|
C语言
C语言常见库函数的模拟实现
C语言常见库函数的模拟实现
57 0
|
C语言
模拟库函数strcpy
关于库函数strcpy()的详细内容,跳转文章:《C语言:字符串拷贝函数strcpy()》
33 0
|
C语言
C语言库函数之 qsort 讲解、使用及模拟实现(下)
C语言库函数之 qsort 讲解、使用及模拟实现(下)
55 0
|
6月前
|
C语言 存储
C语言—部分库函数的模拟实现
C语言—部分库函数的模拟实现
|
6月前
|
算法
库函数讲解及模拟实现库函数
库函数讲解及模拟实现库函数
21 0
模拟实现库函数,strtsr,memmove.
<1>主页:C语言的前男友 <2>知识讲解:模拟实现 库函数 strstr,memmove <3>创作者:C语言的前男友 <4>开发环境:Visual Studio 2022 <5>前言:学习了strstr,memnove等库里面的内存相关的函数,功能非常的强大。今天我们来模拟实现一下。
|
11月前
库函数的模拟实现
库函数的模拟实现
40 0
|
11月前
模拟实现库函数strlen
模拟实现库函数strlen
28 0
|
存储 安全 C语言
模拟实现一些库函数(2)(上)
模拟实现一些库函数(2)(上)
49 0
|
C语言
模拟实现一些库函数(1)(下)
模拟实现一些库函数(1)(下)
36 0