模拟实现函数库中的常用函数,1实现strcpy 2.实现strcat 3.实现strstr 4.实现strchr 5.实现strcmp 6.实现memcpy 7.实现memmove,8实现memset

————– 1模拟实现strcpy—————

strcpy函数是将源字符串复制到目标字符串的函数

strcpy函数的思路就是,它是一个字符串,有\0作为结束标志,那么可以用\0作为突破点和条件,具体代码如下:

char* my_strcpy(char *dest, const char *src)
{
    assert(dest);
    assert(src);
    char *ret = src;
    while ((*dest++ = *src++))
    {
        ;
    }
    return ret;
}

————– 1模拟实现strcat—————

strcat函数是将一一个字符串连接到目标字符串的函数

strcat函数的思路是目标字符串有‘\0’结束,那么可以用’\0’作为第一个判断条件,然后源字符串的结束标志‘\0’可以作为第二个判断条件,具体代码如下:

#include//模拟实现strcat字符串连接
#include
void my_strcat(char *dest, char *src)
{
    assert(dest);
    assert(src);
    while (*dest)//第一个\0,判断字符串结束
    {
        dest++;
    }
    while (*dest++ = *src++)//第二个\0并且赋值,判断字符串结束
    {
        ;
    }
}
int main()
{
    char arr1[20] = { "abcd" };
    char arr2[] = { "efgh" };
    my_strcat(arr1, arr2);
    printf("%s", arr1);
    return 0;
}

————– 3模拟实现strstr—————

strstr函数是在字符串中查找子字符串的函数,如果有反悔所在位置,没有返回NULL。

strstr函数的思路就是从母字符串中的第一个字符开始查找,然后一个一个查找,直到子字符串结束或者母字符串结束,具体代码如下:

char* my_strstr(const char *str1, const char *str2)
{
    assert(str1);
    assert(str2);
    if (*str2 == '\0')
    {
        return NULL;
    }
    char *p1 = (char*)str1;//因为str是const修饰,无法修改,便用一个强制转换赋值一个变量来使用
    char *p2 = (char*)str2;
    char *tmp = NULL;//创建一个零时变量,用来存储p1的地址,因为p1在变化
    while (*p1)
    {
        tmp = p1;
        while ((*p1&&*p2) && (*p1 == *p2))
        {
            p1++;
            p2++;
        }
        if (*p2 == '\0')
        {
            return tmp;
        }
        p1++;
    }
    return NULL;
}

————– 4模拟实现strchr—————

strchr函数是在字符串中查找一个字符,如果有返回所在位置,如果没有返回null。

strchr函数的思路是从字符串的首字符开始查找,如果找到就返回所在位置,如果找不到就继续查找,一直带字符串结束‘\0’为止。具体代码如下:

#include//实现strchr
#include
char *my_strchar(const char *str, const char a)
{
    char *p = (char*)str;
    while (*p)
    {
        if (*p == a)
            return p;
        p++;
    }
    return NULL;
}
int main()
{
    char arr1[] = { "assdfg" };
    char a = 'd';
    char *ret = my_strchar(arr1, a);
    printf("%s", ret);
    return 0;
}

————– 4模拟实现strcmp————–

strcmp函数是比较两个字符串的大小,如果目标字符串大于要比的字符串,返回一个正数,等于返回0,小于返回负数。

strcmp函数的思路就是将两个字符串的字符逐个比较,如果比较的字符相同,那么继续比较下一个字符,一直循环到一个字符串结束‘\0’结束,如果字符不同,那么直接结束比较。具体代码如下:

#include//实现strcmp
#include
int my_strcmp(const char *dest, const char *src)
{
    assert(dest);
    assert(src);
    int ret = 0;
    while (!(ret = (*(unsigned char*)dest - *(unsigned char*)src))&&*src)/*当第一个字符相同时,ret==0;那么就要比较第二个字符
                                                                     ,while循环中就要用'!'来表示为真,继续下一个字符的比较
                                                                     要是第一个字符就不同,那么不执行下一句,直接返回差值*/
    {
        dest++;
        src++;
    }
    return ret;
}
int main()
{
    char arr1[] = { "asdfg" };
    char arr2[] = { "asdfgh" };
    int ret = my_strcmp(arr1, arr2);
    printf("%d", ret);
    return 0;
}

———— 6模拟实现memcpy———–

memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。

memcpy函数并不复杂,通过使用count计数器就可以拷贝n字节到dest中,需要注意的是,在函数调用参数设计中,要注意函数参数的类型,应该是void类型,然后在函数内部强制转换成char*类型。具体代码如下:

#include//模拟实现memcpy
void* my_memcpy(void* dest, void *src, int count)
{
    char* pdest = (char*)dest;//void类型无法赋值和*截引用,和++,因此要强制类型转换为char类型,因为count是字节数,不是元素个数。
    char* psrc = (char*)src;
    while (count--)
    {
        *pdest++ = *psrc++;
    }
    return dest;
}
int main()
{
    int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    my_memcpy(arr1+3, arr1, 20);//20是字节数,不是元素个数。
    return 0;
}

———— 7模拟实现memmove———-

memmove用于从src拷贝count个字节到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同

memmove函数的思路和memcpy函数基本相同,只不过memmove不存在覆盖,那么就可以通过判断dest和src的位置来判断是从前到后拷贝还是从后向前拷贝。第一种方法是:如果dest在src前边,那么就需要从前向后拷贝,如果dest在src后边从后向前拷贝,就不存在覆盖。第二种方法是:判断dest是否在src和src+count之间,如果在,那就从后向前拷贝,其余的从前向后拷贝,就不存在覆盖内容,具体代码如下:

#include//模拟实现memmove函数。
void* my_memmove(void* dest, const void*src, int count)
{
    char* pdest = (char*)dest;
    char* psrc = (char*)src;
    //if (pdest < psrc)//从前向后赋值//这种是通过目标和源的未知判断是从前向后还是从后向前赋值
    //{
    //  while (count--)
    //  {
    //      *pdest++ = *psrc++;
    //  }
    //}
    //else             //从后向前赋值
    //{
    //  while (count--)
    //  {
    //      *(pdest + count) = *(psrc + count);
    //  }
    //}
    if ((pdest > psrc) && (pdest < (psrc + count)))//目标地址在源和count之间,从后向前,别的从前向后
    {
        while (count--)
        {
            *(pdest + count) = *(psrc + count);
        }
    }
    else
    {
        while (count--)
        {
            *pdest++ = *psrc++;
        }
    }
    return dest;
}
int main()
{
    int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    my_memmove(arr1+3,arr1 , 20);
    int i = 0;
    for (i = 0; i < 9; i++)
    {
        printf("%d", arr1[i]);
    }
    return 0;
}

———— 8模拟实现memset———-

函数原型:void* memset (void * ptr, int ch, size_t num );

参数解释:ptr:目标地址 value:要替换的值, num:要替换的大小,单位(字节)

函数功能:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s。

void* Memset(void* ptr, int ch, size_t num)
{
    assert(ptr);
    char* dest = (char*)ptr;

    while (num--)             
    {
        *dest = ch;
        dest++;
    }
    return (void*)dest;
}

void test_memset()
{
    char a[10] = { 0 };
    Memset(a, 'a', 10);

    for (int i = 0; i < 10; i++)
    {
        cout << a[i] << " ";
    }
}

你可能感兴趣的:(C,库,函数)