学习C语言之 了解字符串函数和内存函数

字符函数和字符串函数

        C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。

  1.库函数介绍

        1.1、strlen——求字符串长度

        size_t strlen (const char* str);

        注:

        a、字符串以 ' \0 ' 作为结束标志,strlen函数返回的是在字符串 ' \0 ' 前面出现的字符个数(不包含 ' \0 ' )。

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

        c、注意函数的返回值为 size_t ,是无符号的。

演示如下:

//strlen 函数使用
//strlen 函数返回字符串长度,不计算'\0'
int main()
{
	char ch[] = "abcd";
	int a = strlen(ch);			//将strlen返回值赋给a 。
	printf("%d\n", a);			//打印结果 4 。可见strlen不计算 '\0' 。
	printf("%d\n",strlen(ch));	//打印结果 4 。直接使用strlen返回值。

	return 0;
}

        1.2、strcpy——字符串拷贝

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

        注:

        a、源字符串必须以 ' \0 ' 结束。

        b、会将源字符串中的 ' \0 ' 拷贝到目标空间。

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

        c、目标空间必须可修改。

演示如下:

//strcpy 函数使用
//strcpy 函数实现字符串拷贝功能
//将第二个操作数中的字符串拷贝到第一个字符串中
int main()
{
	char ch1[20] = "*********";
	char ch2[] = "abcde";
	//strcpy(ch1, ch2);
	//printf("%s\n", ch1);	//打印结果 abcde 。说明'\0'也被拷贝进ch1了。
	printf("%s\n", strcpy(ch1, ch2));	//打印结果 abcde 。说明strcpy返回值是ch1的地址。
	return 0;
}

        1.3、strcat——字符串追加

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

        注:

        a、源字符串必须以 ' \0 ' 结束。

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

        c、目标空间必须可修改。

演示如下:

//strcat 函数使用
strcat 函数实现字符串追加功能
//将第二个操作数中的字符串追加到第一个字符串后面
int main()
{
	char ch1[20] = "****\0***";
	char ch2[] = "abcd";
	//strcat(ch1, ch2);
	//printf("%s\n", ch1);	//打印结果****abcd。说明是从ch1中的 '\0'开始粘贴的。
	printf("%s\n", strcat(ch1, ch2));	//打印结果****abcd。说明strcat返回值是ch1地址。
	return 0;
}

        1.4、strcmp——字符串比较

        int strcmp ( const char* str1, const char* str2 );

        注:

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

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

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

演示如下:

//strcmp 函数使用
//strcmp 比较的是对应位字符的ASCII码值。
//根据ASCII码值比较结果返回 <0 、 >0 或0。
int main()
{
	char ch1[20] = "abcde";
	char ch2[] = "abcde";
	char ch3[] = "abb";

	int ret1 = strcmp(ch1, ch2);
	if (ret1 > 0)
	{
		printf(">\n");
	}
	else if (ret1 < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");  //打印结果 = 。可见strcmp只比较到'\0'处,跟数组长度无关。
	}

	int ret2 = strcmp(ch1, ch3);
	if (ret2 > 0)
	{
		printf(">\n");	//打印结果 > 。因为C的ASCII码大于b的ASCII码。
	}
	else if (ret2 < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");  
	}


	return 0;
}

        1.5、strncpy——字符串拷贝

        char* strncpy ( char* destination, const char* source, size_t num );

        注:

        a、从源字符串拷贝num个字符到目标空间。

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

演示如下:

//strncpy 函数使用
//拷贝指定数量个字符。
int main()
{
	char ch1[20] = "abcdefg";
	char ch2[] = "bjlak";

	strncpy(ch1, ch2, 2);
	printf("%s\n", ch1);	//打印结果 bjcdefg 。strcpy只拷贝了 前两个字符。
	return 0;
}

        1.6、strncat——字符串追加

        char* strncat ( char* destination, const char* source,size_t num );

        注:

        a、追加num个字符        

演示如下:

//strncat 函数使用
//追加指定数量个字符。
int main()
{
	char ch1[20] = "abcde ";
	char ch2[] = "bbbbbb";
	strncat(ch1, ch2, 3);
	printf("%s\n", ch1);	//打印结果 abcde bbb 。strncat 只追加了3个字符。
	return 0;
}

        1.7、strncmp——字符串比较

        int strncmp ( const char* str1, const char* 2, size_t num );

        注:

        a、比较到两个字符不一样 或者 一个字符串结束 或者 num个字符全部比较完。

演示如下:

//strncmp 函数使用
//比较指定数量个字符
int main()
{
	char ch1[20] = "abcdef";
	char ch2[] = "abcddd";
	int ret1 = strncmp(ch1, ch2, 3);
	if (ret1 > 0)
	{
		printf(">\n");
	}
	else if (ret1 < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");  //打印结果 = 。strncmp只比较了3个字符,所以是 = 。
	}
		
	int ret2 = strncmp(ch1, ch2,5);
	if (ret2 > 0)
	{
		printf(">\n");	//打印结果 > 。strncmp比较了5个字符,所以是 > 。
	}
	else if (ret2 < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");  
	}
	return 0;
}

        1.8、strstr——字符串查找

        char* strstr ( const char* str1, const char* str2 );

        注:

        a、在str1中查找str2

演示如下:

//strstr 函数使用
//strstr 函数实现查找字符串功能
//从第一个操作数中查找第二个操作数
//如果在第一个字符串中找到第二个字符串
//返回第一个字符串中第二个字符串的首字符地址
//找不到返回NULL
int main()
{
	char ch1[] = "abcdefgh";
	char ch2[] = "cde";
	char ch3[] = "cdd";

	char* find1 = strstr(ch1, ch2);
	char* find2 = strstr(ch1, ch3);
	printf("%s\n", find1);			//打印结果 cdefgh 。说明返回的是abcdefgh 中 cde的c地址。
	printf("%s\n", find2);			//打印结果 (NULL) 。 不建议这样使用,建议先if判断再使用

	printf("%s\n", strstr(ch1, ch2));	//打印结果 cdefgh 。说明返回的是abcdefgh 中 cde的c地址。
	return 0;
}

        1.9、strtok——分解字符串

        char* strtok ( char* str, const char* sep );

        注:

        a、sep参数是个字符串,定义了用作分隔符的字符集合。

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

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

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

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

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

演示如下:

//strtok 函数使用
//strtok 函数实现将字符串按指定字符分割。
//strtok 会保存当次分隔符的地址
//新参数输入NULL时,它会调用之前保存的地址。
//字符串中没有指定字符时,它会返回NULL。
int main()
{
	char ch1[] = "www.abc dd! e. f@d.com";
	char ch2[] = ".@ ";
	char tmp[30] = { 0 };
	strcpy(tmp,ch1);		//strtok会操作字符串,一般用拷贝的数组作为参数。

	char* test1 = strtok(tmp, ch2);
	printf("%s\n", test1);			//打印结果 www ,分隔符是 '.',从ch1中找到ch2中的字符,将ch1分割。

	char* test3 = strtok(NULL, ch2);
	printf("%s\n", test3);			//打印结果 abc ,分隔符是 ' ',输入为NULL,从上次分隔符开始往下分割。

	char* test4 = strtok(NULL, ch2);
	printf("%s\n", test4);			//打印结果 dd! ,分隔符是 ' ',输入为NULL,从上次分隔符开始往下分割。

	char* test2 = strtok(tmp, ch2);
	printf("%s\n", test2);			//打印结果是 www,分隔符是 '.'。可见strtok记录的并不是字符串,而是之前的地址。

	return 0;
}

这样使用太繁琐,简化如下:

//上面使用太麻烦,不可能每次写很多行
int main()
{
	char ch1[] = "www.abc dd! e. f@d.com";
	char ch2[] = ".@ ";
	char tmp[30] = { 0 };
	strcpy(tmp,ch1);		//strtok会操作字符串,一般用拷贝的数组作为参数。


	char* test1 = NULL;
	for (test1 = strtok(tmp, ch2); test1 != NULL; test1 = strtok(NULL, ch2))
	{
		printf("%s\n", test1);
		//打印结果
		//www
		//abc
		//dd!
		//e
		//f
		//d
		//com
	}

	return 0;
}

        1.10、strerror——错误信息报告,返回错误码所对应的错误信息

        char* strerror (int errnum);

演示如下:

//strerror 函数使用
//strerror 函数返回参数对应的错误信息。

int main()
{
	printf("%s\n", strerror(5));	
	//打印结果 Input/output error 。即错误代码编号5的错误信息是输入输出错误
	//strerror 函数使用场景为出现错误代码时输出错误信息。
	//如 if(XXXX)  printf("%s\n",strerror(errno));
	//这里的errno 是当前错误代码,使用时需要 #include <errno.h>
	return 0;
}

        perror——错误信息打印。

演示如下:

    

//perror 函数使用
//perror 函数可打印错误信息。
int main()
{
	perror("abdc");		//运行结果,打印 abdc: No error ,字符串abdc 无错误。
	//perror函数会直接打印错误信息。
	return 0;
}

    字符操作函数

        字符分类函数,参数符合条件返回真

        函数名——条件

        iscntrl——任何控制字符

        isspace——空白字符:空格 ' ' ,换页 ' \f ' ,换行 ' \n ',回车 ' \r ',制表符 ' \t ' 或垂直制表符 ' \v '

        isdigit——十进制数字 0 - 9

        isxdigit——十六进制数字,包括所有十进制数字,小写字母a - f,大写字母 A - F

        islower——小写字母 a - z

        isupper——大写字母 A - Z

        isalpha —— 字母a - z 或 A - Z

        isalnum——字母或者数字,a - z,A - Z,0 - 9

        ispunct ——标点符号,任何不属于数字或者字母的圆形字符(可打印)

        isgraph——任何图形字符

        isprint——任何可打印字符,包括图形字符和空白字符

演示如下:

//字符分类函数介绍
//使用方法基本相同,测试十进制数字分类isdigit 和大写字母分类isupper
//使用字符分类函数需要 #include <ctype.h>

#include <ctype.h>
int main()
{
	char c1 = 'A';
	char c2 = '3';

	int ret1 = isdigit(c1);		//判断c1 是不是十进制数字
	int ret2 = isupper(c1);		//判断c1 是不是大写字母。
	printf("%d\n", ret1);		//打印结果 0 。 c1不是十进制数字,返回结果是 0 。
	printf("%d\n", ret2);		//打印结果 1 。	c1是大写字母,返回结果是 1 (非0)。

	int ret3 = isdigit(c2);		//判断c2是不是十进制数字
	int ret4 = isupper(c2);		//判断c2是不是大写字母。
	printf("%d\n", ret3);		//打印结果 4 。	c2是十进制数字,返回结果是 4 (非0)。
	printf("%d\n", ret4);		//打印结果 0 。	c2不是大写字母,返回结果是 0。

	//字符分类函数,字符不符合分类返回 0 ,符合分类返回非0数字。

	return 0;
}

        字符转换函数

        int tolower( int c ); ——把大写字母转换成小写字母

        int toupper( int c );——把小写字母转换成大写字母

演示如下:

//字符转换函数
//tolower 可以将大写字母转换成小写字母
//使用 tolower 函数需要 #include <stdlib.h>
#include <stdlib.h>

int main()
{
	char ch1 = 'A';
	ch1 = tolower(ch1);

	printf("%c\n", ch1);	//打印结果是 a 。ch1被转换成小写字母a。

	char ch2[] = "AbCdEf";

	int len = strlen(ch2);
	int i = 0;
	for (i = 0; i < len; i++)
	{
		if (isupper(ch2[i]))	//如果ch2[i]是大写字母,则将其转换为小写字母
		{
			ch2[i] = tolower(ch2[i]);
		}
		printf("%c ", ch2[i]);		//打印结果 a b c d e f 。 ch2 数组中的大写字母被转换成小写字母了。
	}

	return 0;
}

        内存操作函数

        1.11、memcpy——内存拷贝

        void* memcpy ( void* destination, const void* source,size_t num );

        注:

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

        b、这个函数在遇到 ' \0 ' 的时候不会停下来。

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

演示如下:

//memcpy 函数使用
//memcpy 可以实现内存拷贝。
//可以对非字符类元素进行拷贝。

int main()
{
	int a[20] = { 1,2,3,4,5,6,7,8,9,0 };
	int b[20] = { 0 };

	memcpy(b, a, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", b[i]);	//打印结果 1 2 3 4 5 0 0 0 0 0 ,数组a中的前5个整型数字拷贝到数组b中了。
	}
	//memcpy可以拷贝指定数量个字节。
	//int类型元素是4个字节,20个字节就是5个元素。

	return 0;
}

        1.12、memmove——拷贝重叠内存块

        void* memove ( void* destination,const void* source,size_t num );

        注:

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

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

演示如下:

//memmove 函数使用
//memmove 可以把源地址往后的指定数量个元素拷贝到目标地址
//功能和memcpy相似,但C语言标准中,memcpy不能拷贝重叠的内存地址上的内容
//memmove 可以拷贝重叠地址上的内容。
//有些编译器中memcpy也能做到memmove的功能

int main()
{
	int a[10] = { 1,2,3,4,5,6,7,8,9,0 };

	memmove(a + 3, a, 20);	//把地址a开始的20个字节拷贝到a+3开始的20个字节中。

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", a[i]); //打印结果 1 2 3 1 2 3 4 5 9 0
	}
	printf("\n");
	int b[10] = { 1,2,3,4,5,6,7,8,9,0 };
	memmove(b, b + 2, 20);	//把地址a开始的20个字节拷贝到a+3开始的20个字节中

	for (i = 0; i < 10; i++)
	{
		printf("%d ",b[i]); //打印结果 3 4 5 6 7 6 7 8 9 0
	}


	return 0;
}

        1.13、memcmp——内存比较函数

        int memcmp ( const void* ptr1, const void* ptr2, size_t num );

        注:

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

        b、将内存中数据以 unsigned char 类型值比较。

        c、两个内存块中第一个不相等的字节对比,ptr1小于ptr2,返回小于0的数字。

        d、两个内存块相等,返回0。

        e、两个内存块中第一个不相等的字节对比,ptr1大于ptr2,返回大于0的数字。

演示如下:

//memcmp 函数使用
//memcmp 函数用于比较两个地址中指定字节的内容是否相等
//相等返回0
//目标地址内容小于源地址返回<0的数
//目标地址内容大于源地址返回>0的数

int main()
{
	int arr1[] = { 1,2,3,4,5,6,6,7 };
	int arr2[] = { 1,2,2,4,5,6 };
	int a = memcmp(arr1, arr2, 8);		//比较arr1和arr2前8个字节内容。这里是前两个整型。
	int b = memcmp(arr1, arr2, 12);		//比较arr1和arr2前20个字节内容。这里是前五个整型。

	printf("%d\n", a);	//打印结果 0 。arr1和arr2前8个字节相等,返回 0 。
	printf("%d\n", b);	//打印结果 1 。arr1前12个字节比arr2大,返回 1 。

	return 0;
}

        1.14、memset——内存设置函数

        void* memset ( void* dest, int c, size_t count);

        注:

        a、将 dest 地址往后 count 个字节设置成 c 。

演示如下:

//memset 函数使用
//memset 函数可以将目标地址中的指定数量个字节设置成指定值

int main()
{
	int a[10] = { 1,2,3,4,5,6,7,8,9 };
	memset(a, 0, 8);	//将a地址往后的前8个字节设置成0 。

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", a[i]); //打印结果 0 0 3 4 5 6 7 8 9 0 ,
	}
	//要注意,memset是按字节设置数,而不是按整型!

	return 0;
}

2.库函数的模拟实现

        2.1、模拟实现strlen

        a、计数器版本

演示如下:

//模拟实现strlen函数
//计数器版本
int my_strlen(const char* arr)
{
	assert(arr);	//断言,防止空指针
	int count = 0;	//设置计数器
	
	//*arr 内容不为 0 则判断为真,循环继续,为 0 则判断为假,循环停止。
	//arr是char*,其中的内容判断为字符,'\0'的ASCII码就是 0 。
	//因此,将 *arr != ’\0’ 简化成  *arr 。
	while (*arr)	
	{
		arr++;
		count++;
	}
	return count;
}

int main()
{
	char ch[] = "abcd";
	int a = my_strlen(ch);
	printf("%d\n", a);				//打印结果 4 。
	printf("%d\n", my_strlen(ch));	//打印结果 4 。
	return 0;
}

        b、递归版本

演示如下:

//模拟实现strlen函数
//递归版本
int my_strlen(const char* arr)
{
	assert(arr);	//断言,防止空指针
	if (*arr)		//*arr 不为'\0'则返回 1+ my_strlen(arr + 1) 
		return 1 + my_strlen(arr + 1);
	else
		return 0;	//*arr 为'\0' 则返回0
	//即每次进入下一个地址,下一个地址不为 '\0'就 +1
}

int main()
{
	char ch[] = "abcd";
	int a = my_strlen(ch);
	printf("%d\n", a);				//打印结果 4 。
	printf("%d\n", my_strlen(ch));	//打印结果 4 。
	return 0;
}

        c、指针减指针版本

演示如下:

//模拟实现strlen函数
//指针减指针版本
int my_strlen(const char* arr)
{
	assert(arr);	//断言,防止空指针
	char* ori = (char*)arr;	//记录起点处地址。
	while (*ori)		//若*arr 不为'\0',则进入下一个字符地址
	{
		ori++;
	}
	//地址到 *arr == '\0' 时循环停止
	return ori - arr;	//用'\0'处的地址 减去起始地址,就是元素个数。
}

int main()
{
	char ch[] = "abcd";
	int a = my_strlen(ch);
	printf("%d\n", a);				//打印结果 4 。
	printf("%d\n", my_strlen(ch));	//打印结果 4 。
	return 0;
}

        2.2、模拟实现strcpy

演示如下:

//模拟实现strcpy

char* my_strcpy(char* arr1, const char* arr2)
{
	assert(arr1 && arr2); //断言,arr1 和arr2 都不能是空指针
	char* ch = arr1;		//记录arr1地址。
	int len = strlen(arr2);	//计算arr2长度。
	int i = 0;
	for (i = 0; i <= len; i++)	//按arr2长度 +1 循环赋值,将arr2中的字符赋给arr1。
	{
		*arr1++ = *arr2++;
	}
	return ch;
}

int main()
{
	char ch1[20] = "*********";
	char ch2[] = "abcde";
	//my_strcpy(ch1, ch2);
	//printf("%s\n", ch1);	//打印结果 abcde 。
	printf("%s\n", my_strcpy(ch1, ch2));	//打印结果abcde 。
	return 0;
}

        2.3、模拟实现strcat

演示如下:

//strcat 模拟实现

char* my_strcat(char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	char* ch = arr1;	//将arr1赋给 ch。
	while (*ch)			//找到 *ch == '\0' 的ch。
	{
		ch++;
	}
	while (*ch++ = *arr2++)	//将arr2中的字符粘贴到ch中,然后++。直到 *arr2 中出现'\0'
	{
		;
	}
	return arr1;
}

int main()
{
	char ch1[20] = "****\0***";
	char ch2[] = "abcd";
	//my_strcat(ch1, ch2);
	//printf("%s\n", ch1);	//打印结果****abcd。
	printf("%s\n", my_strcat(ch1, ch2));	//打印结果****abcd。
	return 0;
}

        2.4、模拟实现strcmp

演示如下:

//模拟实现 strcmp 函数

int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);	//断言
	while (*arr1 == *arr2)	//*arr1 等于 *arr2 时,arr1++,arr2++。
	{
		if (*arr1 == '\0')		//如果*arr1 == '\0',返回0。
		{
			return 0;
		}
		arr1++;
		arr2++;
	}
	//*arr1 != *arr2 时跳出循环
	return *arr1 - *arr2;	//返回*arr1 - *arr2
}

int main()
{
	char ch1[20] = "abcde";
	char ch2[] = "abcde";
	char ch3[] = "abb";
	
	int ret1 = my_strcmp(ch1, ch2);
	if (ret1 > 0)
	{
		printf(">\n");
	}
	else if (ret1 < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");  //打印结果 = 。
	}
	
	int ret2 = my_strcmp(ch1, ch3);
	if (ret2 > 0)
	{
		printf(">\n");	//打印结果 > 。
	}
	else if (ret2 < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");  
	}
	return 0;
}

        2.5、模拟实现strstr

演示如下:

//模拟实现strstr 函数

char* my_strstr(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);		//断言
	char* find = (char*)arr1;	//将arr1首元素地址赋给 find。
	char* c1 = NULL;			//定义字符指针c1,c2,后续用
	char* c2 = NULL;
	
	if (*arr2 == '\0')			//arr2 如果是空指针,返回字符串arr1地址。
	{
		return ((char*)arr1);
	}

	
	while (*find)	//find 中还有字符就继续查找
	{
		c1 = find;				//记录当次查找的起始地址
		c2 = (char*)arr2;		//从arr2 的首字符开始查找
		while (*c2 && (*c1 == *c2))	//c2不为0,且c1中字符与c2中字符一样则继续往后查找
		{
			c1++;		//下一个字符
			c2++;		//下一个字符
		}
		if (*c2 == '\0')	//c1中字符和c2中字符不一样时,判断c2是否为结束符。
		{
			return find;	//c2是结束符说明找到了arr2中的所有字符串。
		}

		find++;		//从find开始没找到arr2,则从find++开始查找。
	}
	return NULL;
}

int main()
{
	char ch1[] = "abcdefgh";
	char ch2[] = "cde";
	char ch3[] = "cdd";
	
	char* find1 = my_strstr(ch1, ch2);
	char* find2 = my_strstr(ch1, ch3);
	printf("%s\n", find1);			//打印结果 cdefgh 。
	printf("%s\n", find2);			//打印结果 (NULL) 。 
	
	printf("%s\n", my_strstr(ch1, ch2));	//打印结果 cdefgh 。
	return 0;
}

        2.6、模拟实现memcpy

演示如下:


//模拟实现 memcpy 函数

void* my_memcpy(void* destination, const void* source, int num)
{
	assert(destination && source);
	char* ret = (char*)destination;
	while (num--)
	{
		*ret = *(char*)source;
		ret++;
		source = (char*)source + 1;
	}
	return destination;
}

int main()
{
	int a[20] = { 1,2,3,4,5,6,7,8,9,0 };
	int b[20] = { 0 };

	my_memcpy(b, a, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", b[i]);	//打印结果 1 2 3 4 5 0 0 0 0 0 ,数组a中的前5个整型数字拷贝到数组b中了。
	}
	//memcpy可以拷贝指定数量个字节。
	//int类型元素是4个字节,20个字节就是5个元素。

	return 0;
}

        2.7、模拟实现memmove

演示如下:

//模拟实现memmove 函数

void* my_memmove(void* dest,const void* src, int num)
{
	assert(dest && src); //断言
	char* ret = (char*)dest;	//将dest赋给 ret

	if (dest < src)		//目标地址在源地址前面时,从前往后拷贝
	{
		while (num--)
		{
			*ret = *(char*)src;
			ret = ret + 1;
			src = (char*)src + 1;
		}
	}
	else				//目标地址在源地址后面时,从后往前拷贝
	{
		while (num--)
		{
			*(ret + num) = *((char*)src + num);
		}
	}
	return dest;
}

int main()
{
	int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
	
	my_memmove(a + 3, a, 20);	//把地址a开始的20个字节拷贝到a+3开始的20个字节中。
	
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", a[i]); //打印结果 1 2 3 1 2 3 4 5 9 0
	}

	printf("\n");

	int b[10] = { 1,2,3,4,5,6,7,8,9,0 };
	my_memmove(b, b + 2, 20);	//把地址a开始的20个字节拷贝到a+3开始的20个字节中
	
	for (i = 0; i < 10; i++)
	{
		printf("%d ",b[i]); //打印结果 3 4 5 6 7 6 7 8 9 0
	}
	return 0;
}

  • 12
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值