strcpy和strncpy和memcpy和memmove四个函数对比分析

参考:
参考1
参考2

问题提出

  1. sizeof(str) 和 strlen(str) 的区别?
  2. strcpy 和 strncpy 的区别?
  3. strcpy 和 strncpy 函数为什么要返回dest的副本?
  4. strcpy 和 strncpy 函数的缺陷有哪些?你如何解决?有替代函数吗?

问题解决

  1. sizeof(str) 和 strlen(str) 的区别?

sizeof(str) 会计算str所占总空间的字节数,strlen(str)会计算字符串的有效长度,不包括’\0’。

#include<iostream>
using namespace std;

int main()
{
	// 测试 strlen() 和 sizeof()
	char str[] = { "hello hello" };
	int len1 = strlen(str);
	int len2 = sizeof(str);
	cout << len1 << endl;  // len1 = 11
	cout << len2 << endl;  // len2 = 12

	system("pause");
	return 0;
}
  1. strcpy 和 strncpy 的区别?

区别是strncpy有参数控制拷贝的个数,不像strcpy,strncpy不会向dest追加结束标记’\0’

strcpy特点:

  1. 将src拷贝到dest中,包括’\0’字符
  2. 为避免溢出dest指向的空间应该足够大能够放的下src

strncpy特点:

  1. 如果src的前n个字节不含’\0’字符,则结果不会以’\0’字符结束。
  2. 如果src的长度小于n个字节,则以’\0’填充dest直到复制完n个字节。
  3. 如果src中有’\0’,例如:“abc\0def” 则只会复制abc
  4. src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
  1. strcpy 和 strncpy 函数为什么要返回dest的副本?

为了实现函数连级使用 例如:strcpy(str3, strcpy(str1,str2))

  1. strcpy 和 strncpy 函数的缺陷有哪些?你如何解决?有替代函数吗?

strcpy函数缺陷:

  1. 要程序员保证dest大小能够存放src包括’\0’,一旦dest空间不够会在别的内存中写入,很危险。可能有覆盖问题

strncpy函数缺陷:

  1. 如果src的前n个字符不包含’\0’字符,strncpy函数不会在末尾补上’\0’,打印时会有乱码。
  2. 如果src的长度小于n个字节,则以’\0’填充dest直到复制完n个字节,如果n远大于src这会导致效率问题。可能有覆盖问题

解决缺陷的方法

  1. 正确使用这两个函数:
    1.使用strcpy时人工确定dest大小足够
    2.使用strncpy时,确保 n = dest - 1
    例如:
    strncpy(path, src, sizeof(path) - 1);
    path[sizeof(path) - 1] = ‘\0’;

  2. 使用替代函数:memmove(),解决src可能被覆盖问题

strcpy()实现

char* my_strcpy(char* dest, const char* src)
{
	//assert(dest != NULL && src != NULL);
	char* save = dest;
	while ((*dest++ = *src++) != '\0');
	return save;
}

strncpy() 实现

char* my_strncpy(char* dest, const char* src, size_t count)
{
	//assert(dest != NULL && src != NULL);
	char* save = dest;
	while (count--)
	{
		if (*src != '\0') *dest++ = *src++;
		else *dest++ = '\0';
	}
	return save;
}

memcpy()实现

void* my_memcpy(void* dest, const void* src, size_t count)
{
	assert(dest != nullptr && src != nullptr);
	char* p = (char*)dest;
	char* q = (char*)src;
	if (p == q) return p;
	while (count--)
	{
		*p++ = *q++;
	}
	return dest;
}

memmove()实现

void* my_memmove(void* dest, const void* src, size_t count)
{
	assert(dest != nullptr && src != nullptr);
	if (dest < src) // dest尾巴可能和src头部重合
	{
		char* p = (char*)dest;
		char* q = (char*)src;
		while (count--)
		{
			*p++ = *q++;
		}
	}
	else            // src尾部可能和dest头部重合 
	{
		char* p = (char*)dest + count;
		char* q = (char*)src + count;
		while (count--)
		{
			*--p = *--q;
		}
	}
	return dest;
}

测试用例

int main()
{
	// 测试 my_strcpy 和 my_strncpy
	char dest[20];
	my_strcpy(dest, str);
	my_strncpy(dest, str, 15);
	cout << dest << endl;

	// 测试 my_memcpy 和 my_memmove
	char s1[] = "123456789";
	char s2[] = "123456789";
	my_memcpy(s1 + 2, s1, 5);
	cout << "my_memcpy: " << s1 << endl;
	my_memmove(s2 + 2, s2, 5);
	cout << "my_memmove: " << s2 << endl;

	system("pause");
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值