• 字符串,字符,内存函数介绍


    一,strlen

    在这里插入图片描述
    1,strlen函数是计算字符串长度的函数
    2,他的返回值类型是size_t也就是unsigned int 类型

    int main()
    {
    	char arr1[] = "hello";
    	char arr2[] = "hello world";
    
    	if (strlen(arr1) - strlen(arr2)>0)
    	{
    		printf(">\n");
    	}
    	else
    	{
    		printf("<\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    我们第一眼看到这个函数的时候大概率以为输出的结果是小于号,实则不然,这就是因为strlen函数的返回值是unsigned int类型,上面两个数相减结果是-6,他的补码是
    11111111111111111111111111111010
    但这是无符号类型的整数,其实这是一个非常大的数字。
    3,模拟实现

    size_t my_strlen(const char* str)
    {
    	char* start = str;
    	while (*str)
    	{
    		str++;
    	}
    	return str - start;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    二,strcpy

    在这里插入图片描述
    1,字符串拷贝函数,将源头字符串的内容拷贝到目标字符串中
    2,目标字符串要有足够大的空间
    3,字符串在拷贝的过程中,‘\0’,也进行了拷贝
    在这里插入图片描述
    在这里插入图片描述

    4,源头字符串中必须有’\0’
    在这里插入图片描述
    在这里插入图片描述
    可以看到拷贝发生了错误。

    5,目标空间可以被修改
    6,模拟实现

    char* my_strcpy(char* dest, const char* src)
    {
    	char* ret = dest;
    	assert(dest && src);
    	while (*dest++ = *src++)
    	{
    		;
    	}
    	return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    三,strcat

    在这里插入图片描述

    int main()
    {
    	char arr1[20] = "hello ";
    	char arr2[] = "world";
    	strcat(arr1, arr2);
    	printf("%s\n", arr1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    1,这是一个字符串链接函数
    2,目标空间足够大
    3,目标空间可以被修改
    4,目标字符串中与源头字符串中都含有’\0’
    (1)若源头字符串中不含有’\0’,会与strcpy函数源头字符串不含结束标志结果一致
    (2)函数的连接点是目标字符串中’\0’的位置
    在这里插入图片描述
    在这里插入图片描述
    5,与strcpy函数相同结束标志’\0’也进行了拷贝
    6,能否实现自己给自己连接呢?答案是否定的(你可以想一下这是为什么?)
    7,模拟实现

    char* my_strcat(char* dest, const char* src)
    {
    	assert(dest && src);
    	char* ret = dest;
    	while (*dest)
    	{
    		dest++;
    	}
    	while (*dest++ = *src++)
    	{
    		;
    	}
    	return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    四,strcmp

    在这里插入图片描述
    1,字符串比较函数,一个字节一个字节的比较字符串的ascall码,若str1大于str2则返回大于0 的值,相反返回小于0的值,否则返回0.

    int main()
    {
    	char arr1[] = "abce";
    	char arr2[] = "abcd";
    	int ret = strcmp(arr1, arr2);
    	printf("%d\n", ret);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    2,两个字符串中必须含有’\0’,
    在这里插入图片描述
    如图,两个字符串明明相等,却返回-1.并且还造成了越界访问。
    3,模拟实现

    int my_strcmp(const char* arr1, const char* arr2)
    {
    	assert(arr1 && arr2);
    	while (*arr1 == *arr2)
    	{
    		if (*arr1 == '\0')
    			return 0;
    		arr1++;
    		arr2++;
    	}
    	return *arr1 - *arr2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    五,strncpy

    在这里插入图片描述

    int main()
    {
    	char arr1[20] = "hello world";
    	char arr2[] = "xxxxxx";
    	strncpy(arr1, arr2, 5);
    	printf("%5s\n", arr1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    1,有长度限制的字符串拷贝函数
    2,目标空间足够大

    3,模拟实现

    char* my_strcpy(char* arr1, const char* arr2, size_t num)
    {
    	assert(arr1 && arr2);
    	char* ret = arr1;
    	while (num&&*arr2)
    	{
    		*arr1 = *arr2;
    		arr1++;
    		arr2++;
    		num--;
    	}
    	while (num--)
    	{
    		*arr1 = '\0';
    		arr1++;
    	}
    	return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    六,strncat

    在这里插入图片描述
    这个函数就可以实现自己给自己追加了

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

    在这里插入图片描述

    1,有长度限制的字符串追加函数
    2,目标空间足够大
    3,在追加num个字符之后,还会追加上一个’\0’
    在这里插入图片描述
    在这里插入图片描述
    4,模拟实现

    char* my_strncat(char* dest, const char* src, size_t num)
    {
    	assert(dest && src);
    	char* ret =dest;
    	while (*dest)
    	{
    		dest++;
    	}
    	while (num-- && *src != '\0')
    	{
    		*dest = *src;
    		dest++;
    		src++;
    	}
    	if (*src == '\0')
    	{
    		*dest = *src;
    		return ret;
    	}
    	else
    	{
    		*dest = '\0';
    	}
    	return ret;
    }
    
    • 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

    七,strncmp

    在这里插入图片描述

    1,有长度限制的字符串比较函数
    2,相比较几个,就比较几个
    在这里插入图片描述

    八,strstr

    在这里插入图片描述
    1,字符串查找函数
    2,在主串中查找子串,返回字串在主串中的地址,若在主串中找到多次字串那么返回第一次找到的地址。
    在这里插入图片描述
    3,模拟实现

    char* my_strstr(const char* arr1, const char* arr2)
    {
    	assert(arr1 && arr2);
    	char* p = arr1;
    	char* s1 = p;
    	char* s2 = arr2;
    	while (*p)
    	{
    		s1 = p;
    		while (*s2&&*s1 == *s2)
    		{
    			s1++;
    			s2++;
    		}
    		if (*s2 == '\0')
    			return p;
    		p++;
    	}
    	return NULL;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    但这是一种暴力求解方法,如果追求更高的效率,可以看后期的KMP算法。

    九,strtok

    在这里插入图片描述
    1,sep参数是个字符串,定义了用作分隔符的字符集合
    第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
    2,函数会将分隔符位置改成’\0’(真的会把字符串改变,所以通常先拷贝一下源字符串)
    3,此函数具有记忆功能,如果一个字符串需要分隔多次,只需第一次传入字符串地址
    后面传空指针为参数即可。
    4,函数返回值为指向分割后的字符串的指针。
    在这里插入图片描述
    在这里插入图片描述

    十,strerror

    在这里插入图片描述
    这是一个将错误码,转化成错误信息的函数。
    在这里插入图片描述

    十一,perror

    perror=strerror+printf
    在这里插入图片描述

    十二,字符函数

    在这里插入图片描述
    这里有很多函数,我们介绍几个
    例如,将小写字母全部转化成大写字母的代码。

    int main()
    {
    	char arr[] = "Hello world";
    	char* pc = arr;
    	while (*pc)
    	{
    		if (islower(*pc))
    		{
    			*pc = toupper(*pc);
    		}
    		pc++;
    	}
    	printf("%s\n", arr);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    运行结果
    在这里插入图片描述

    十三,memcpy

    在这里插入图片描述
    1,这个函数会将 num个字节的内容 从source中拷贝到 destination中。
    在这里插入图片描述
    2,模拟实现

    void* my_memcpy(void* dest, const void* src, size_t num)
    {
    	assert(dest && src);
    	void* ret = dest;
    	while (num--)
    	{
    		*(char*)dest = *(char*)src;
    		dest = (char*)dest + 1;
    		src = (char*)src + 1;
    	}
    	return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    十四,memmove

    在这里插入图片描述
    1,与memcpy大致相同,和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
    在这里插入图片描述
    2,模拟实现

    void* my_memmove(void* dest, const void* src, size_t num)
    {
    	assert(dest && src);
    	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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    十五,memcmp

    在这里插入图片描述
    1,比较从ptr1呵ptr2开始的num个字节的内容
    2,返回值与上述的strcmp相同
    在这里插入图片描述
    3,模拟实现

    int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
    {
    	assert(ptr1 && ptr2);
    	while (num--)
    	{
    		if (*(char*)ptr1 == *(char*)ptr2)
    		{
    			ptr1 = (char*)ptr1 + 1;
    			ptr2 = (char*)ptr2 + 1;
    		}
    		else
    		{
    			return *(char*)ptr1 - *(char*)ptr2;
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    【Java 基础篇】Java List 使用指南:深入解析列表操作
    学习、实习、校招
    java8特性,lambda表达式,简写的演变及应用
    升级 webpack5 + vue-cli5
    LeetCode 面试题 16.03. 交点
    Visual Studio远程连接Linux编译代码时,头文件在/usr/include中找不到,文件存在于/usr/include的子目录中
    【C语言】堆排序详解
    天气API调用
    爬虫学习笔记 -- 实战某电影网(lxml库版)
    命令执行绕过 [GXYCTF2019]Ping Ping Ping1
  • 原文地址:https://blog.csdn.net/Djsnxbjans/article/details/126848544