字符串+内存函数咋用咋实现呢?让我来告诉你


在学习这篇文档之前,我相信大家没有了解过strcat strstr strtok strerror等这样的函数吧,而在我们日常学习的过程中,这些函数或多或少都会给我们起到很大帮助,那么我们接下来一起来学习一下各种字符串与内存相关的函数吧!
请添加图片描述


重点内容

重点介绍处理字符和字符串的库函数的使用和注意事项

  • 求字符串长度
    • strlen
  • 长度不受限制的字符串函数
    • strcpy
    • strcat
    • strcmp
  • 长度受限制的字符串函数
    • strncpy
    • strncat
    • strncmp
  • 字符串查找
    • strstr
    • strtok
  • 错误信息报告
    • strerror
  • 字符操作
  • 内存操作函数
    • memcpy
    • memmove
    • memset
    • memcmp

1.strlen:求字符串长度

请添加图片描述

  1. 参数:size_t strlen(const char* str);

    • sizeof 操作符 计算大小的
  2. 字符串以'\0'作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包
    '\0' )。

  3. 参数指向的字符串必须要以 '\0'结束。

  4. 注意函数的返回值为size_t(unsigned int),是无符号的( 易错 )

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
    	if ((int)strlen("abc") - (int)strlen("abcdef") > 0)
    		printf(">");
    	else
    		printf("<=");//right
    
    
    	if (strlen("abc") - strlen("abcdef") > 0)
    		printf(">");//前-后=-3,strlen函数返回类型是size_t,-3会变成一个超级大的数>0
    	else
    		printf("<=");
    
    	return 0;
    }
    
  5. 使用

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
    	int len = strlen("abcdef");
    	printf("%d\n", len);
    
    	printf("%d\n", strlen("abcdef"));//链式访问
    
    	return 0;
    }
    
    
  6. 模拟实现

    #include<stdio.h>
    #include<string.h>
    #include <assert.h>
    
    int my_strlen(const char* str)//字符串不想被修改:加const
    {
    	assert(str);//断言:判断指针是否有效
    	int count = 0;
    	while (*str)//*str!='\0'
    	{
    		count++;
    		str++;
    	}
    	return count;
    }
    
    int main()
    {
    	int len = my_strlen("abcdef");
    	printf("%d\n", len);//6
    
    	return 0;
    }
    

2.strcpy:字符串的拷贝

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HFMk3VHi-1645708291767)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645660693583.png)]

  1. 参数:char* strcpy(char * destination, const char * source );

  2. 将源字符串指向的字符串复制到目标指向的数组中,包括\0字符(并在该点停止)。

  3. 源字符串必须以 ‘\0’ 结束。

  4. 会将源字符串中的 ‘\0’ 拷贝到目标空间。

  5. 目标空间必须足够大,以确保能存放源字符串。

  6. 目标空间必须可变。

  7. 使用

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
    	char arr1[] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0' };
    	char arr2[20] = "xxxxxxxxxxxx";
    
    	printf("%s\n", strcpy(arr2, arr1));//返回arr2的起始地址
    	return 0;
    }
    
    
  8. 模拟实现

    #include<stdio.h>
    #include<string.h>
    
    //方法一
    char* my_strcpy(char* dest, const char* src)
    {
    	char* ret = dest;
    	assert(dest && src);
    	//当*src为\0时,赋值过去\0,整个表达式为0,退出
    	while (*src)
    	{
    		*dest = *src;
    		dest++;
    		src++;
    	}
    	*dest = *src;
    	//⽅法⼆
    	
    	return ret;//返回⽬标字符串,模拟实现就是这么做的,⽅便进⾏链式访问
    }
    
    //方法二
    char* my_strcpy(char* dest, const char* src)
    {
    	char* ret = dest;
    	assert(dest && src);
    	while (*dest++ = *src++)
    	{
    		;
    	}
    	
    	return ret;//返回⽬标字符串,模拟实现就是这么做的,⽅便进⾏链式访问
    }
    
    int main()
    {
    	//char arr1[] = "abcdef";
    	char arr1[] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0' };//没有\0拷贝失败
    	char arr2[20] = "xxxxxxxxxxxx";
    
    	//const char* p = "xxxxxxxxxx";//⽬标空间必须可变。
    	//my_strlen(p, arr1);//err 不能是const->⽬标空间必须可变
    
    	my_strcpy(arr2, arr1);//\0也应该拷⻉过去
    	printf("%s\n", arr2);//abcdef 后⾯的*不打印->因为把\0拷⻉过去了,遇到\0就不打印后⾯的东⻄了
    
    
    	return 0;
    }
    

    注意事项:尽量不能返回局部变量的地址,返回局部变量可以

    #include<stdio.h>
    
    //尽量不能返回局部变量的地址,返回局部变量可以
    int Add(int x, int y)
    {
    	int z = x + y;
    	return z;
    }
    //空间销毁并不是地址被销毁
    int* test()
    {
    	int a = 10;//0x0012ff40
    	return &a;//不能返回局部变量的地址
    }
    
    int main()
    {
    	// p = 0x0012ff40
    	int* p = test();
    	*p = 20;//⾮法访问内存
    	return 0;
    }
    

3.strcat:字符串的连接

在这里插入图片描述

  1. 参数:char * strcat ( char * destination, const char * source );

  2. 将源字符串的副本追加到目标字符串,目标字符串中的\0会被源字符串的第一个字符覆盖,并且在新拼接的两个字符串末尾会有\0

  3. 源字符串必须以 ‘\0’ 结束。

  4. 目标空间必须有足够的大,能容纳下源字符串的内容。

  5. 目标空间必须可修改。

  6. 字符串自己给自己追加,不会输出任何结果

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
    	char arr1[30] = "hello";
    	
    	strcat(arr1, arr1);
    	printf("%s\n", arr1);
    	return 0;
    }
    
  7. 使用

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
    	char arr1[30] = "hello";//⽬标空间必须⾜够⼤
    	char arr2[] = "world";
    	//char arr2[] = { 'h','e','l','l','o' };//err
    	//char arr2[] = { 'h','e','l','l','o','\0' };//原字符串必须以\0结束
    	strcat(arr1, arr2);
    	printf("%s\n", arr1);
    	return 0;
    }
    
  8. 模拟实现

    #include<stdio.h>
    #include<string.h>
    
    char* my_strcat(char* dest, const char* src)
    {
    	char* ret = dest;
    	assert(dest && src);//判断空指针,不能判断是否是野指针
    	//1. ⽬标空间中的\0
    	while (*dest)//*dest!=‘\0’
    	{
    		dest++;
    	}
    	//2. 追加内容到⽬标空间-strcpy
    	while (*dest++ = *src++)
    	{
    		;
    	}
    	return ret;//规定返回char*,⽬标空间起始地址
    }
    int main()
    {
    	char arr1[30] = "hello";
    	char arr2[] = "world";// {'w', 'o', 'r', 'l', 'd', '\0'};
    
    	printf("%s\n", my_strcat(arr1, arr2));
    
    	return 0;
    }
    
    注意:两种错误方法
    //到\0的位置,后置++就把\0跳过了
    while(*dest++)
    {
         ;
    }
    //当arr1为空字符串(只有\0)的时候,上来就先把\0跳过去了
    while(*++dest)
    {
         ;
    }
    

4.strcmp:字符串的比较

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G1e2dqpc-1645708291769)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645663792555.png)]

  1. 参数:int strcmp ( const char * str1, const char * str2 );

  2. 这个函数刚开始会比较每个字符串的第一个字符的ASCII码值,之后继续比较,直到字符不同,或直到\0返回空指针。

  3. 标准规定:

    • 第一个字符串大于第二个字符串,则返回大于0的数字
    • 第一个字符串等于第二个字符串,则返回0
    • 第一个字符串小于第二个字符串,则返回小于0的数字
  4. 模拟实现

    #include<stdio.h>
    #include<string.h>
    #include<assert.h>
    
    int my_strcmp(const char* str1, const char* str2)
    {
    	assert(str1 && str2);
    	while (*str1 == *str2)//\0==\0也会进⼊循环
    	{
    		if (*str1 == '\0')
    			return 0;
    
    		str1++;
    		str2++;
    	}
    	return *str1 - *str2;
    	/*if (*str1 > *str2)//>0
    		return 1;
    	else//<0
    		return -1;*/
    }
    int main()
    {
    	//strcmp - 字符串⽐较
    	//⽐较是对应位置上的字符⼤⼩-⽐的是ASCII码值
    	char arr1[] = "abc";
    	char arr2[] = "abc";
    
    	int ret = my_strcmp(arr1, arr2);
    
    	if (ret < 0)//ret==-1 err
    	{
    		printf("arr1<arr2");
    	}
    	else if (ret > 0)//ret==1 err
    	{
    		printf("arr1>arr2");
    	}
    	else
    	{
    		printf("arr1==arr2");
    	}
    
    	return 0;
    }
    
  5. 判断字符串相等不能用==

    if("abc"=="abq")
    //字符串的首地址一定不同->错误
    

5.strncpy:指定个数的字符串拷贝

在这里插入图片描述

  1. 参数:char * strncat ( char * destination, const char * source, size_t num );

  2. 拷贝num个字符从源字符串到目标空间。

  3. 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加\0,直到num个。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nt5zsN1a-1645708291771)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645665049534.png)]

  4. 使用:

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
    	char arr1[] = "xxxxxxxxxxxxxxxxx";
    	char arr2[] = "hello world";
    	strncpy(arr1, arr2, 5);//helloxxxxxxxxxxxx
    	printf("%s\n", arr1);
    }
    
  5. 模拟实现

    #include<stdio.h>
    #include<string.h>
    #include<assert.h>
    
    char* my_strncpy(char* dest, const char* src, size_t n)
    {
        assert(dest&&src);
    
        char* ret = dest;
        while (n--)
        {
            *dest++ = *src++;
        }
        return ret;
    }
    
    int main()
    {
    	char arr1[] = "xxxxxxxxxxxxxxxxx";
    	char arr2[] = "hello";
    	my_strncpy(arr1, arr2, 5);
    	printf("%s\n", arr1);
    }
    
    

6.strncat:指定个数的字符串连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YKHLIjNr-1645708291772)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645701653192.png)]

  1. 参数:char * strncat ( char * destination, const char * source, size_t num );

  2. 使用:

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
    	char arr1[20] = "hello";
    	char arr2[] = "world";
    	strncat(arr1, arr2, 3);
    	printf("%s\n", arr1);//hellowor
    	return 0;
    }
    
  3. 模拟实现:

    #include<stdio.h>     
    #include<string.h>
    #include<assert.h>
    
    void my_strncat(char* arr1, const char* arr2, int n)
    {
    	assert(arr1 && arr2);
    
    	char* p = arr1;
    	char* q = arr2;
    
    	while (*p)
    	{
    		p++;
    	}
    	while (n--)
    	{
    		*p = *q;
    		p++;
    		q++;
    	}
    	*p = '\0';
    	
    }
    
    int main()
    {
    	char arr1[30] = "hello";
    	const char arr2[] = "world";
    	int num = 0;
    	scanf("%d", &num);
    
    	my_strncat(arr1, arr2, num);
    	printf("%s\n", arr1);
    	return 0;
    }
    

7.strncmp:指定个数的字符串比较

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qmxfcvW7-1645708291773)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645702740972.png)]

  1. 参数:int strncmp ( const char * str1, const char * str2, size_t num );

  2. 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

  3. 返回值说明
    <0arr1<arr2
    >0arr1>arr2
    =0arr1==arr2
  4. 使用:

    #include<stdio.h>     
    #include<string.h>
    
    int main()
    {
    	char arr1[] = "abcwef";
    	char arr2[] = "abcqqqqqq";
    	int ret = strncmp(arr1, arr2, 4);
    
    	if (ret < 0)
    	{
    		printf("arr1<arr2");
    	}
    	else if (ret > 0)
    	{
    		printf("arr1>arr2");//w>q
    	}
    	else
    	{
    		printf("arr1==arr2");
    	}
    
    	return 0;
    }
    
    
    
  5. 模拟实现:

    #include<stdio.h>     
    #include<string.h>
    #include<assert.h>
    
    int my_strncmp(const char* str1, const char* str2, int n)
    {
    	assert(str1 && str2);
    	while (n--)
    	{
    		if (*str1 == *str2)
    		{
    			str1++;
    			str2++;
    		}
    		else if (*str1 - *str2 < 0)
    		{
    			return -1;
    		}
    		else
    		{
    			return 1;
    		}
    	}
    	return 0;
    }
    
    int main()
    {
    	char arr1[] = "abcwef";
    	char arr2[] = "abcqqqqqq";
    	int ret = my_strncmp(arr1, arr2, 4);
    
    	if (ret < 0)
    	{
    		printf("arr1<arr2");
    	}
    	else if (ret > 0)
    	{
    		printf("arr1>arr2");//w>q
    	}
    	else
    	{
    		printf("arr1==arr2");
    	}
    
    	return 0;
    }
    
    

8.strstr:字符串查找函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-18Ceyf2p-1645708291773)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645703959873.png)]

  1. 参数:char * strstr ( const char *str1, const char * str2);

  2. 返回一个指向str1中首次出现str2的指针,如果str2不是str1的一部分,则返回一个空指针。

  3. 使用:

    #include<stdio.h>     
    #include<string.h>
    
    int main()
    {
    	char arr1[] = "abbbcdef";
    	char arr2[] = "bbcq";
    
    	char* ret = strstr(arr1, arr2);
    
    	if (NULL == ret)
    		printf("没找到\n");
    	else
    		printf("%s\n", ret);
    
    	return 0;
    }
    
  4. 模拟实现:

    #include<stdio.h>     
    #include<string.h>
    #include<assert.h>
    
    char* my_strstr(const char* str, const char* substr)//找substr
    {
    	const char* s1 = str;//原来的字符串的起始地址
    	const char* s2 = substr;//目标字符串起始字符串地址
    	const char* cur = str;
    
    	assert(str && substr);
    	if (*substr == '\0')//判断子字符串是否是空字符串-没法查找
    	{
    		return (char*)str;//规定:返回str
    	}
    	while (*cur)//*cur!=‘\0’ 后⾯还有元素可以寻找
    	{
    		s1 = cur;
    		s2 = substr;
    		while (*s1 && *s2 && *s1 == *s2)
    		{
    			s1++;
    			s2++;
    		}
    		if (*s2 == '\0')//把⼦串找到了,返回它的地址
    			return (char*)cur;
    
    		cur++;//这个字符不相等,向后移
    	}
    	return NULL;//未找到
    }
    
    
    int main()
    {
    	char arr1[] = "abbbcdef";
    	char arr2[] = "bbcq";
    
    	char* ret = my_strstr(arr1, arr2);
    
    	if (NULL == ret)
    		printf("没找到\n");
    	else
    		printf("%s\n", ret);
    
    	return 0;
    }
    

9.strtok:把一个字符串分割成几个字符串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tv4gc3kx-1645708291774)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645704493427.png)]

  1. 参数:char * strtok ( char * str, const char * sep );

  2. sep参数是个字符串,定义了用作分隔符的字符集合

  3. 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标
    记。

  4. strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
    strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
    并且可修改。)

  5. strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
    中的位置。

  6. strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
    记。

  7. 如果字符串中不存在更多的标记,则返回 NULL 指针。

  8. 使用:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    	const char* p = "@.#";//要先加分隔符
    	char arr[] = "shuaige@zui.shuai#hehe";
    	char buf[50] = { 0 };
    	strcpy(buf, arr);
    	char* str = NULL;//先初始化
    
    	for (str = strtok(buf, p); str != NULL; str = strtok(NULL, p))
    	{
    		printf("%s\n", str);
    	}
    
    	return 0;
    }
    
    //注意事项:
    //1.strtok函数找第⼀个标记的时候,函数的第⼀个参数不是NULL
    //2.strtok函数找⾮第⼀个标记的时候,函数的第⼀个参数是NULL
    

10.strerror:返回错误码,所对应的错误信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YqAkCxrD-1645708291776)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645705181977.png)]

  1. 参数:char * strerror ( int errnum );

  2. 在C语言中,规定了一些信息—错误码(错误信息)

    • 0 - “No Error”
    • 1-
    • 2-
    //strerror - 可以把错误码翻译成错误信息
    
    int main()
    {
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		printf("%s\n", strerror(i));
    	}
    	return 0;
    }
    
  3. 使用:

    //C语⾔可以操作⽂件
    //打开⽂件 - fopen
    //
    //当库函数使⽤的时候,发⽣错误会把errno这个全局的错误变量设置为本次执⾏库函数产⽣的错误码
    //errno是C语⾔提供的⼀个全局变量,可以直接使⽤,放在errno.h⽂件中的
    #include <stdio.h>
    #include <errno.h>
    
    int main()
    {
    	//打开⽂件
    	FILE* pf = fopen("test.txt", "r");
    	if (NULL == pf)
    	{
    		//出错误的原因是什么
    		printf("%s\n", strerror(errno));
    		return 0;//打开失败直接结束
    	}
    	//读⽂件
    	//...
    
    	//关闭⽂件
    	fclose(pf);
    	pf = NULL;
    
    	return 0;
    }
    

11.常见字符分类函数

函数如果他的参数符合下列条件就返回真
iscntrl任何控制字符
isspace 空空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母af,大写字母AF
islower小写字母a~z
isupper大写字母A~Z
isalpha字母az或AZ
isalnum字母或者数字,az,AZ,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符
举例:
#include<stdio.h>
#include<ctype.h>

//判断是否是空⽩字符
int main()
{
	//printf("%d\n", isspace(' '));//8-打印看不⻅的字符时返回⼀个⾮0值
	//printf("%d\n", isspace(' '));//0-是随机的
	
	char ch = 'w';
	if (isspace(ch))
	{
		//空⽩字符
	}
	else
	{
		//⾮空⽩字符
	}
	return 0;
}

//判断是不是数字
int main()
{
	char ch = '0';
	//if (ch >= '0' && ch <= '9')//效率低
	//{

	//}
	if (isdigit(ch))
	{

	}

	//转换函数:⼤写字⺟⼩写字⺟互换
	char ch = 0;
	ch = getchar();
	if (islower(ch))//判断⼩写
	{
		ch = toupper(ch);//⼩写->⼤写
	}
	else//判断⼤写
	{
		ch = tolower(ch);//⼤写->⼩写
	}
	printf("%c\n", ch);

	return 0;
}

12.memcpy:指定个数的字符串拷贝

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rTLdBvx7-1645708291777)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645706219737.png)]

  1. 参数:void * memcpy ( void * destination, const void * source, size_t num );

  2. 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

  3. 这个函数在遇到 ‘\0’ 的时候并不会停下来。

  4. 如果source和destination有任何的重叠,复制的结果都是未定义的。

  5. 使用:

    #include<stdio.h>
    #include<ctype.h>
    
    int main()
    {
    	//char arr1[] = "abcdef";
    	//char arr2[20] = { 0 };
    	//strcpy(arr2, arr1);//只能拷⻉字符串的
    
    	int arr3[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr4[5] = { 0 };
    	memcpy(arr4, arr3, 20);
    	int i = 0;
    	for (i = 0; i < 5; i++)
    	{
    		printf("%d\n", arr4[i]);//1 2 3 4 5
    	}
    	return 0;
    }
    
  6. 模拟实现

    #include<stdio.h>
    #include<ctype.h>
    #include<assert.h>
    
    void* my_memcpy(void* dest, const void* src, size_t num)
    {
    	void* ret = dest;
    	assert(dest && src);
    
    	while (num--)
    	{
    		*(char*)dest = *(char*)src;//(char*)dest 一个一个字节操作起来会更加细致
    		dest = (char*)dest + 1;//dest++;err 强制类型转换都是临时的,需要每次都强转
    		src = (char*)src + 1;//src++;err
    	}
    
    	return ret;//要求规定:返回一个void*类型的指针
    }
    
    
    int main()
    {
    	int arr3[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr4[5] = { 0 };
    
    	my_memcpy(arr4, arr3+5, 5*sizeof(arr3[0]));
    
    	int i = 0;
    	for (i = 0; i < 5; i++)
    	{
    		printf("%d\n", arr4[i]);//6 7 8 9 10
    	}
    
    	return 0;
    }
    
    反例:当原字符串和目标字符串重叠的时候->memmove可以解决
    

13.memmove:包含了memcpy

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ssCtpGNX-1645708291778)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645707414211.png)]

  1. 参数:void * memmove ( void * destination, const void * source, size_t num );

  2. 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

  3. 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

  4. 举例:

    #include<stdio.h>
    #include<ctype.h>
    #include<assert.h>
    
    //反例:当原字符串和⽬标字符串重叠的时候->memmove可以解决
    //memmove
    void* my_memcpy(void* dest, const void* src, size_t num)
    {
    	void* ret = dest;
    	assert(dest && src);
    
    	while (num--)
    	{
    		*(char*)dest = *(char*)src;
    		dest = (char*)dest + 1;
    		src = (char*)src + 1;
    	}
    
    	return ret;
    }
    
    //memmove实现
    void* my_memmove(void* dest, const void* src, size_t num)
    {
    	void* ret = dest;
    	assert(dest && src);//保证两个指针的有效性
    
    	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;
    }
    
    void test1()
    {
    	int arr3[] = { 1,2,3,4,5,6,7,8,9,10 };
    
    	//my_memcpy(arr3+2, arr3, 5 * sizeof(arr3[0]));//1 2 1 2 1 2 1 8 9 10
    	//my_memmove(arr3, arr3 + 2, 20);//3 4 5 6 7 6 7 8 9 10
    
    	memcpy(arr3+2, arr3, 20);//1 2 1 2 3 4 5 8 9 10
    	//库⾥⾯的memcpy⽀持,但是C语⾔只要求:
    	//memcpy能拷⻉不重叠的内存空间就可以了
    	//memmove去处理那些重叠内存拷⻉
    	//但是发现VS上memcpy也能实现重叠拷⻉(超常发挥了)
    
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr3[i]);
    	}
    }
    int main()
    {
    	test1();
    	return 0;
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8bGN6c6z-1645708291780)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645707723024.png)]

14.memcmp:内存比较函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXcjfntz-1645708291780)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645707857844.png)]

  1. 参数:

    int memcmp ( const void * ptr1,
    const void * ptr2, 
    size_t num );
    
  2. 比较从ptr1和ptr2指针开始的num个字节

  3. 返回值:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HuUKxl8S-1645708291781)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645707881992.png)]

15.memset函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5wR5uBjL-1645708291782)(E:\博客\C语言专区\C语言进阶版本\字符串+内存函数的介绍\字符串+内存函数的介绍.assets\1645707960197.png)]

  1. 使用

    int main()
    {
    	//char arr[20] = { 0 };
    	//memset(arr, 'x', 10);
    	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    	memset(arr, 0, 10);
    	//00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 ...
    	return 0;
    }
    
     memcpy(arr3+2, arr3, 5 * sizeof(arr3[0]));//1 2 1 2 1 2 1 8 9 10
    	//my_memmove(arr3, arr3 + 2, 20);//3 4 5 6 7 6 7 8 9 10
    
    	memcpy(arr3+2, arr3, 20);//1 2 1 2 3 4 5 8 9 10
    	//库⾥⾯的memcpy⽀持,但是C语⾔只要求:
    	//memcpy能拷⻉不重叠的内存空间就可以了
    	//memmove去处理那些重叠内存拷⻉
    	//但是发现VS上memcpy也能实现重叠拷⻉(超常发挥了)
    
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr3[i]);
    	}
    }
    int main()
    {
    	test1();
    	return 0;
    }
    

    [外链图片转存中...(img-8bGN6c6z-1645708291780)]


到这里,C语言中常见的字符串就已经讲解完毕了,希望你能理解的透彻!
喜欢的话一件三连熬~

  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 27
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加勒比海涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值