【C语言】模拟实现库函数

//模拟实现strlen
//strlen->计算字符串的元素个数,碰到'\0'结束
//方法一:计数器法
#include<assert.h>
int My_strlen(const char* arr)
{
    //断言,确保指针的安全性
    assert(arr);
    int count = 0;
    //strlen计算'\0'之前的元素个数
    while (*arr != '\0')
    {
        //++寻找下一个元素
        arr++;
        count++;
    }
    return count;
}
int main()
{
    char arr[] = "abcdef";
    int ret = My_strlen(arr);
    printf("%d\n", ret);
    return 0;
}

//方法二:递归法
int My_strlen(const char* arr)
{
    //断言,确保指针的安全性
    assert(arr);
    if (*arr++)
    {
        return 1 + My_strlen(arr);
    }
    return 0;
}
int main()
{
    char arr[] = "abcdef";
    int ret = My_strlen(arr);
    printf("%d\n", ret);
    return 0;
}

//方法三:指针法
//指针-指针 = 元素个数
int My_strlen(const char* arr)
{
    //断言,确保指针的安全性
    assert(arr);
    //首元素地址
    char* ret = arr;
    //得到'\0'的地址
    while (*arr != '\0')
    {
        arr++;
    }
    return arr - ret;
}
int main()
{
    char arr[] = "abcdef";
    int ret = My_strlen(arr);
    printf("%d\n", ret);
    return 0;
}

//模拟实现strcpy
//strcpy->字符串拷贝函数
//函数构成:char* strcpy(char* 目标空间,const char* 源头(要拷贝的值))
//将源头字符串包括'\0'传值到目标空间内,以'\0'为结束标志
//注意:目标空间的空间要大于源头空间
#include<assert.h>
char* My_strcpy(char* arr2, const char* arr1)
{
    //断言,防止arr2或arr1为空指针
    assert(arr2 && arr1);
    //因为最后要返回目标空间(arr2)的首元素地址,我们先将arr2首元素地址存储起来
    char* ret = arr2;
    //将arr1的值依次传给arr2,当最后将'\0'传给arr2后
    //判断条件为0,跳出循环
    while (*arr2++ = *arr1++)
    {
        ;
    }
    return ret;
}
int main()
{
    char arr1[] = "abcdef";
    char arr2[10] = "cdef";
    My_strcpy(arr2, arr1);
    printf("%s\n", arr2);
    return 0;
}

 #include<stdio.h>
//strcmp模拟实现
//strcmp比较原则为:元素一对一进行比较:
//大于返回>0
//小于返回>0
//当全部元素包括'\0'都相等时,返回0
#include<assert.h>
int My_strcmp(const char* arr1, const char* arr2)
{
    //断言,确保指针可用性
    assert(arr1 && arr2);
    while (*arr1 == *arr2)
    {
        //当arr1与arr2的元素全部相等
        if (*arr1 == '\0')
        {
            return 0;
        }
        arr1++;
        arr2++;
    }
    if (*arr1 > *arr2)
    {
        return *arr1 - *arr2;
    }
    else
    {
        return *arr1 - *arr2;
    }
}
int main()
{
    char arr1[] = "abcdef";
    char arr2[] = "abcdef";
    int ret = My_strcmp(arr1, arr2);
    printf("%d\n", ret);
    return 0;
}

//模拟实现strcar
//strcar连接字符串函数
//构造:char* strcar(char*连接目标,const char*需连接的字符串)
//寻找目标字符串的'\0',将需要连接的字符串的首地址放到'\0'处依次往后(包括需连接的字符串的'\0')
//直到遇到'\0'结束
#include<assert.h>
char* My_strcar(char* arr1,const char* arr2)
{
    //断言,确保指针安全性
    assert(arr1 && arr2);
    char* ret = arr1;
    while (*arr1)
    {
        arr1++;
    }
    while ((*arr1++ = *arr2++))
    {
        ;
    }
    return ret;
}
int main()
{
    char arr1[20] = "abcdef";
    char arr2[] = "ghi";
    My_strcar(arr1, arr2);
    printf("%s\n", arr1);
    return 0;
}

//模拟实现strstr
//strstr函数->arr1,arr2寻找arr1中arr2的字符串
//最后返回arr1中的arr2的字符串首元素往后的字符
//找到第一次出现的字符,并返回后面的字符
char* My_strstr(const char* arr1, const char* arr2)
{
    //定义两个指针用于操作arr1,arr2
    char* s1 = NULL;
    char* s2 = NULL;
    //将arr1的地址存到cp指针内,用于最后寻找相同的元素和最后返回值
    char* cp = (char*)arr1;

    //循环,当*cp为'\0'时,表示arr1里找不到arr2的字符串
    while (*cp)
    {
        s1 = cp;
        s2 = (char*)arr2;
        //当*s1、*s2有为'\0'时
        //跳出循环
        //条件成立arr1与arr2的元素均++
        while (*s1 && *s2 && *s1 == *s2)
        {
            s1++;
            s2++;
        }
        //当*s2为'\0'时,表示已经寻找到
        if (*s1 == '\0')
        {
            return cp;
        }
        cp++;
    }
    return NULL;
}
int main()
{
    char arr1[] = "abbcdef";
    char arr2[] = "bcd";
    char* ret = My_strstr(arr1, arr2);
    if (NULL == ret)
    {
        printf("NULL\n");
    }
    printf("%s\n", ret);
    return 0;
}

//模拟实现memcpy
//我们学习过strcpy字符串拷贝库函数
//当我们想拷贝不同类型元素时,我们可以使用memcpy函数
//void* memcpy(void* 目标空间,const void* 源头, size_t 拷贝元素字节个数)
//我们可以通过字节个数来决定我们要拷贝多少个元素到目标空间
// 最后返回拷贝完后目标空间的首元素地址
//遇到'\0'结束
//注意:目标空间要比源头数组空间大
#include<assert.h>
void* My_memcpy(void* arr2, const void* arr1, size_t sz)
{
    assert(arr2 && arr1);
    //保存arr2的首元素地址,便于之后返回
    void* p = arr2;
    //我们将arr2与arr1强转为char*有两个理由:
    //1.void*指针不能进行*和++、--操作
    //2.char*++、--跳过一个字节,而sz为我们要拷贝的字节个数
    //无论什么类型,我们可以一个一个字节的拷贝,这样适用于任何类型的拷贝
    while (sz--)
    {
        *((char*)arr2) = *((char*)arr1);
        arr2 = (char*)arr2 + 1;
        arr1 = (char*)arr1 + 1;
    }
    return p;
}
int main()
{
    float arr1[] = { 1.0f,2.0f,3.0f,4.0f,5.0f,6.0f };
    float arr2[10] = { 0.0f };
    My_memcpy(arr2, arr1, 20);
    int sz = sizeof(arr2) / sizeof(arr2[0]);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%.1f ", arr2[i]);
    }
    return 0;
}

当我们想将源头元素拷贝到源头数组里呢?memcpy可行吗?

我们发现好像并不行,由此我们引出memmove函数

接下来我们就模拟实现一下memmove函数


//模拟实现memmove
//memmove函数与memcpy基本相同
//可以说memmove函数包含了memcpy的功能
#include<assert.h>
void* My_memmove(void* arr2, const void* arr1, size_t sz)
{
    assert(arr2 && arr1);
    //保存arr2的首元素地址,便于之后返回
    void* p = arr2;
    //分情况,如果arr1在arr2的右边
    //因为地址是由低到高变化的
    if (arr2 < arr1)
    {
        //从前->后交换
        while (sz--)
        {
            *((char*)arr2) = *((char*)arr1);
            arr2 = (char*)arr2 + 1;
            arr1 = (char*)arr1 + 1;
        }
    }
    //arr1在arr2的左边时
    //或者arr1和arr2元素不重叠
    else
    {
        while (sz--)
        {
            //从后->前交换
            //arr2+sz(字节个数),sz--后 == 字节个数-1
            //访问到arr2的最后一个元素空间
            //arr1也一样的道理
            *((char*)arr2 + sz) = *((char*)arr1 + sz);
        }
    }
    return p;
}
int main()
{
    float arr1[] = { 1.0f,2.0f,3.0f,4.0f,5.0f,6.0f };
    //float arr2[10] = { 0.0f };
    //My_memcpy(arr1+2, arr1, 12);
    My_memmove(arr1 + 2, arr1, 12);
    int sz = sizeof(arr1) / sizeof(arr1[0]);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%.1f ", arr1[i]);
    }
    return 0;
}

原理图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值