• 字符串函数的模拟实现(上)


    strlen函数

    size_t strlen ( const char * str );
    
    • 1

    strlen函数的返回值是size_t

    什么是size_t ?

    size_t: typedef unsigned int size_t (在32位操作系统下)

    也就是unsigned int

    strlen函数的使用

    int main()
    {
        char arr1[] = "hello world";
        int len = strlen(arr1);
        printf("%d\n", len);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    模拟实现strlen

    //计数器的方法
    int my_strlen(char* str)
    {
    	int count = 0;
    	while (*str != '\0')
    	{
    		count++;
    		str++;
    	}
    	return count;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    //指针减去指针的方法
    int my_strlen(char* str)
    {
    	char* tmp = str;
    	while (*tmp != '\0')
    	{
    		tmp++;
    	}
    	return tmp - str;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //递归的方法
    int my_strlen(char* str)
    {
    	//终止条件
    	if (*str == '\0')
    	{
    		return 0;
    	}
    	return 1 + my_strlen(str + 1);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    1、strlen函数返回的是在字符串中以‘\0’前面出现的字符个数,不包括‘\0’

    但是在sizeof关键字中 会把‘\0’看作占用空间大小 sizeof只看所占空间大小

    2、(易错点) 函数的返回值是无符号整型

    3、如果字符串不是以‘\0’结束的话,strlen函数返回的值是随机值

    strcpy函数

    char * strcpy ( char * destination, const char * source );
    
    • 1

    从source源地址拷贝到destination地址中

    1、目标空间必须足够大,能够容纳源字符串

    2、目标空间必须可变

    3、拷贝到‘\0’的时候,拷贝停止

    xxxxxxxx zhang \0 san

    在拷贝的时候,内存中会存zhang \0 xxx

    由此可证明上述观点

    4、源数据保证要有‘\0’

    strcpy函数的使用

    int main()
    {
        char arr1[] = "hello world";
        char arr2[20] = { 0 };
        strcpy(arr2, arr1);
        puts(arr2);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    模拟实现strcpy

    #include
    char* my_strcpy(char* str1,char* str2)
    {
    	assert(str1 && str2);
    	while (*str1++ = *str2++)
    	{
    		;
    	}
    	return str1;
    }
    int main()
    {
    	char arr1[20] = { 0 };
    	char arr2[] = "abcdef";
    	my_strcpy(arr1, arr2);
    	puts(arr1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    strcat函数

    char * strcat ( char * destination, const char * source );
    
    • 1

    1、目标空间必须足够大,能够容纳下源字符串中的内容

    2、目标空间必须可修改

    3、源字符串必须要以‘\0’结束

    strcat函数的使用

    模拟实现strcat

    #include
    char* my_strcat(char* str1, char* str2)
    {
        assert(str1 && str2);
    	while (*str1 != '\0')
    	{
    		str1++;
    	}
    	while (*str1++ = *str2++)
    	{
    		;
    	}
    	return str1;
    }
    int main()
    {
    	char arr1[30] ="hello world";
    	char arr2[] = "abcdefghi";
    	my_strcat(arr1, arr2);
    	puts(arr1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    strcmp函数

    int strcmp ( const char * str1, const char * str2 )
    
    • 1

    两个字符串比较要用strcmp函数

    在这里插入图片描述

    第一个字符串大于第二个字符串,则返回大于0的数字

    第一个字符串等于第二个字符串,则返回0

    第一个字符串小鱼第二个字符串,则返回小于0的数字

    strcmp函数的使用

    int main()
    {
        char arr1[] = "abcdef";
        char arr2[] = "abcq";
        int ret = strcmp(arr1, arr2);
        if (ret > 0)
        {
            printf(">\n");
        }
        else if (ret == 0)
        {
            printf("==\n");
        }
        else
            printf("<\n");
           
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    模拟实现strcmp

    #include
    int my_strcmp(const char* str1, const char* str2)
    {
        assert(str1 && str2);
        while (*str1 == *str2)
        {
            if (*str1 == '\0')
            {
                return 0;
            }
            str1++;
            str2++;
        }
        return *str1 - *str2;
    }
    
    int main()
    {
        char arr1[] = "abc";
        char arr2[] = "abc";
        int ret = my_strcmp(arr1, arr2);
        if (ret > 0)
        {
            printf(">\n");
        }
        else if (ret == 0)
        {
            printf("==\n");
        }
        else
            printf("<\n");
           
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    memcpy函数

    void * memcpy ( void * destination, const void * source, size_t num )
    
    • 1

    1、memcpy函数在遇到‘\0’的时候 不会停下来

    2、函数从source 的位置开始向后复制num个字节的数据到destnation的位置

    memcpy函数的使用

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

    模拟实现memcpy

    1、模拟实现时,参数类型void* ,是因为不知道具体的数据类型,设计泛型指针更合理

    2、返回目标空间的起始地址

    3、num决定了拷贝的字节数

    #include
    #include
    #include
    void* my_memcpy(void* dest, const void* src, size_t num)
    {
        assert(dest && src);
        // 因为dest要改变 保存起始地址以便返回
        void* ret = dest;
        while (num--)
        {
            *(char*)dest = *(char*)src;
            dest = (char*)dest + 1;
            src = (char*)src + 1;
        }
        return ret;
    }
    int main()
    {
        int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
        int arr2[20] = { 0 };
        my_memcpy(arr2, arr1, 40);
        int i = 0;
        for (i = 0; i < 10; i++)
        {
            printf("%d ", arr2[i]);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    memmove函数

    void * memmove ( void * destination, const void * source, size_t num )
    
    • 1

    memmove函数和memcpy函数的参数一模一样

    memmove函数和memcpy函数比较

    有内存重叠的需要用memmove memcpy函数虽然也能实现memmove的功能,但是C语言标准规定了遇到内存重叠的时候要用memmove函数

    memmove函数的使用

    //把arr1中 从1开始的20个字节的内容复制给从3开始的内存上
    int main()
    {
        int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
        memmove(arr1+2, arr1, 20);
        int i = 0;
        for (i = 0; i < 10; i++)
        {
            printf("%d ", arr1[i]);
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    模拟实现memmove

    当dest在src的前面的时候:有一种情况

    在这里插入图片描述

    当dest在src后面的时候:有两种情况

    在这里插入图片描述

    在这里插入图片描述

    在数组中,地址是由低到高变化的

    当src的地址小于dest的地址时,也就是当src在dest的前面的时候, 从后向前复制

    当src的地址大于dest的地址时,也就是当src在dest的后面的时候, 从前往后复制

    在这里插入图片描述

    void* my_memmove(void* dest, const void* src, size_t num)
    {
        assert(dest && src);
        // 因为dest要改变 保存起始地址以便返回
        void* ret = dest;
        if (dest < src)
        {
            while (num--)
            {
                *(char*)dest = *(char*)src;
                dest = (char*)dest + 1;
                src = (char*)src + 1;
            }
    
        }
        else
        {
            while (num--)
            {
                *((char*)dest + num) = *((char*)src + num);
            }
        }
        
        return ret;
    }
    //把arr1中 从1开始的20个字节的内容复制给从3开始的内存上
    int main()
    {
        int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
        memmove(arr1+2, arr1, 20);
        int i = 0;
        for (i = 0; i < 10; i++)
        {
            printf("%d ", arr1[i]);
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    memcmp函数

    int memcmp ( const void * ptr1, const void * ptr2, size_t num 
    
    • 1

    比较从ptr1和ptr2指针开始的num个字节

    memcmp函数的使用

    #include
    #include
    int main()
    {
        char arr1[] = "hello";
        char arr2[] = "abcde";
        int ret = memcmp(arr1, arr2, 20);
        if (ret > 0)
        {
            printf(">\n");
        }
        else if (ret == 0)
        {
            printf("==\n");
        }
        else
            printf("<\n");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    工作应该选择稳定的、工资低的?还是有挑战的工资高的?
    国内手机安装 Google Play 服务 (GMS/Google Mobile Services)
    element -ui 横向时间轴,时间轴悬浮对应日期
    Qt元对象系统
    python装饰器原理梳理
    BIOS MBR UEFI GPT详解
    数据结构复习笔记6.2:图的存储和遍历
    计算机网络(概述)
    使用 Node.js 和 Azure Function App 自动更新 Elasticsearch 索引
    6-1漏洞利用-FTP漏洞利用
  • 原文地址:https://blog.csdn.net/m0_66032294/article/details/125869882