strcpy、strncpy、memcpy、memmove之间的区别和实现

1.函数声明

char* strcpy(char *d_s, const char *s_s);

char* strcpy(char *d_s, const char *s_s, size_t n);

void* memcpy(void *d_s, const void *s_s, size_t n);

void* memmove(void *d_s, const void *s_s, size_t n);

2.函数理解和区别

strcpy:拷贝s_s指向的内容到d_s,直到遇到字符串结束符'\0',并返回d_s

strncpy:拷贝s_s指向的内容到d_s,拷贝n个字节,并返回d_s

memcpy:拷贝s_s指向的内容到d_s,拷贝n个字节,并返回d_s

memmove:拷贝s_s指向的内容到d_s,拷贝n个字节,并返回d_s

这几个函数,strcpy没有考虑到d_s溢出的情况,程序员只能自己避免这种情况,其余的函数都有参数n做了一个限制

strcpy是遇到结束符之后就不拷贝了,strncpy是拷贝n字节,受结束符影响,但是不会在结束符停止,而是继续剩余个结束符

memcpy传入的是void*,strcpy和strncpy是char*,所以对于其他类型的数据(数组、结构体等),要用memcpy拷贝strcpy和strncpy是不行

不考虑性能问题,memmove应该是最好的,它即考虑到了安全(溢出)通用性(数据类型),还考虑到了地址重叠,其余3个函数,对于地址重叠的情况是不考虑的

对于前面2种情况,4个函数拷贝没有问题,但是对于第3种情况,只有memmove才能正确拷贝

所有函数对于传入的源都用了const限制,这个是很好编程习惯,防止源被修改

3.函数个人实现

下面这些函数的实现和某些系统标准库的实现还是有差别的,在Ubuntu里面,strcpy好像是先计算长度,再把要拷贝的内容复制到一个局部buffer里面,memcpy应该和我的实现应该一样,一个字节一个字节的拷贝,但是应该还有更细节的东西(拷贝效率按字节还是按字拷贝和字节对齐),具体还要看源码

char* my_strcpy(char *d_s, const char *s_s)
{
	if ((NULL == d_s) || (NULL == s_s))
	{
		assert(0);
	}
	char *temp = d_s;
	
	while((*d_s++ = *s_s++) != '\0');
	
	return temp;
}

char* my_strncpy(char *d_s, const char *s_s, size_t n)
{
	if ((NULL == d_s) || (NULL == s_s))
	{
		assert(0);
	}
	char *temp = d_s;
	
	while(n--)
	{
		if ((*d_s = *s_s) != '\0')
		{
			s_s++;
		}
		d_s++;		
	}
	
	
	return temp;
}


void* my_memcpy(void *d_s, const void *s_s, size_t n)
{
	if ((NULL == d_s) || (NULL == s_s))
	{
		assert(0);
	}
	char *temp = (char*)d_s;
	const char *ss_s = (char*)s_s;
	while(n--)
	{
		*temp++ = *ss_s++;
	}
	
	return d_s;
}

void* my_memmove(void *d_s, const void *s_s, size_t n)
{
	if ((NULL == d_s) || (NULL == s_s))
	{
		assert(0);
	}
	char *temp = (char*)d_s;
	const char *ss_s = (char*)s_s;
	if ((s_s >= d_s) || d_s - n >= s_s)//1, 2
	{
		printf("not\n");
		while(n--)
		{
			*temp = *ss_s;
			temp++;
			ss_s++;
		}
	}
	else //3
	{
		printf("yes\n");
		temp = temp + n - 1;
		ss_s = ss_s + n - 1;
		while(n--)
		{
			*temp = *ss_s;;
			temp--;
			ss_s--;
		}

	}
	return d_s;
}

 

1. atof(): 将字符串转换为double类型的值。 例如: ```c++ char str[] = "3.14"; double num = atof(str); printf("%f", num); ``` 结果为:3.140000 2. atoi(): 将字符串转换为int类型的值。 例如: ```c++ char str[] = "1234"; int num = atoi(str); printf("%d", num); ``` 结果为:1234 3. atol(): 将字符串转换为long类型的值。 例如: ```c++ char str[] = "1234567"; long num = atol(str); printf("%ld", num); ``` 结果为:1234567 4. strtod(): 类似于atof(),将字符串转换为double类型的值。 例如: ```c++ char str[] = "3.14"; double num = strtod(str, NULL); printf("%f", num); ``` 结果为:3.140000 5. strtol(): 将字符串转换为long类型的值,同时支持指定转换的基数(例如10进制、16进制等)和错误检查。 例如: ```c++ char str[] = "0110"; long num = strtol(str, NULL, 2); printf("%ld", num); ``` 结果为:6 6. strtoul(): 类似于strtol(),不过返回的是无符号的long类型。 例如: ```c++ char str[] = "0xA"; unsigned long num = strtoul(str, NULL, 16); printf("%lu", num); ``` 结果为:10 7. memset(): 将一段内存区域设置为指定的值。 例如: ```c++ char str[10]; memset(str, 'a', sizeof(str)); printf("%s", str); ``` 结果为:aaaaaaa 8. memcpy(): 将一段内存区域的内容复制到另一段内存区域。 例如: ```c++ char src[] = "hello"; char dst[10]; memcpy(dst, src, sizeof(src)); printf("%s", dst); ``` 结果为:hello 9. memmove(): 和memcpy()类似,但是保证在有重叠的情况下会正确工作。 例如: ```c++ char str[] = "hello"; memmove(str + 2, str, 3); printf("%s", str); ``` 结果为:hehlo 10. memcmp(): 比较两段内存区域的内容是否相等。 例如: ```c++ char str1[] = "hello"; char str2[] = "Hello"; int result = memcmp(str1, str2, 5); printf("%d", result); ``` 结果为:32(h和H的ASCII码差值) 11. memchr(): 在一段内存区域中搜索指定的字符,并返回指向该字符的指针。 例如: ```c++ char str[] = "hello"; char* ptr = (char*)memchr(str, 'l', 5); printf("%s", ptr); ``` 结果为:ll 12. strcpy(): 将一个字符串复制到另一个字符串。 例如: ```c++ char src[] = "hello"; char dst[10]; strcpy(dst, src); printf("%s", dst); ``` 结果为:hello 13. strncpy(): 类似于strcpy(),不过只会复制指定长度的字符。 例如: ```c++ char src[] = "hello"; char dst[10]; strncpy(dst, src, 3); dst[3] = '\0'; printf("%s", dst); ``` 结果为:hel 14. strcat(): 将一个字符串附加到另一个字符串的末尾。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; strcat(str1, str2); printf("%s", str1); ``` 结果为:helloworld 15. strncat(): 类似于strcat(),不过只会附加指定长度的字符。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; strncat(str1, str2, 3); printf("%s", str1); ``` 结果为:helloworld 16. strcmp(): 比较两个字符串是否相等。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; int result = strcmp(str1, str2); printf("%d", result); ``` 结果为:-15 17. strncmp(): 类似于strcmp(),不过只会比较指定长度的字符。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; int result = strncmp(str1, str2, 3); printf("%d", result); ``` 结果为:0 18. strchr(): 在一个字符串中搜索指定的字符,并返回指向该字符的指针。 例如: ```c++ char str[] = "hello"; char* ptr = strchr(str, 'l'); printf("%s", ptr); ``` 结果为:llo 19. strrchr(): 类似于strchr(),不过会从字符串的末尾开始搜索。 例如: ```c++ char str[] = "hello"; char* ptr = strrchr(str, 'l'); printf("%s", ptr); ``` 结果为:lo 20. strstr(): 在一个字符串中搜索指定的子字符串,并返回指向该子字符串的指针。 例如: ```c++ char str[] = "hello world"; char* ptr = strstr(str, "world"); printf("%s", ptr); ``` 结果为:world
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值