字符串操作函数的实现
前言
- 实现strcpy
- 实现strcat
- 实现strstr
- 实现strchr
- 实现strcmp
- 实现memcpy
- 实现memmove
strcpy的实现
- 函数原型
char *MyStrcpy(char *dest, const char *src);
- 实现代码
//该函数不能处理内存重叠现象,故出现了函数memcpy();
//实现strcpy
char *MyStrcpy(char *dest, const char *src) //1.原字符串设置成const,防止被修改;2.返回值为char *,链式访问
{
assert(dest && src); //3.增强代码健壮性
char *ret = dest; //4.同时将\0也拷贝入内。
while (*ret++ = *src++);
return dest;
}
strcat的实现
- 函数原型
char* MyStrcat(char *dest, const char *src);
- 实现代码
char* MyStrcat(char *dest, const char *src)
{
assert(dest&&src);
char *ret = dest;
while (*ret)
{
ret++;
}
while (*ret++ = *src++);
return dest;
}
strstr的实现
- 函数原型
char* MyStrstr(const char *str1,const char *str2);
- 实现代码
char* MyStrstr(const char *str1,const char *str2)
{
assert(str1&&str2);
while (*str1)
{
if (*str1 == *str2)
{
const char *tmp1 = str1;
const char *tmp2 = str2;
while (*tmp1 == *tmp2)
{
tmp1++;
tmp2++;
}
if (*tmp2 == '\0')
{
return str1;
}
}
str1++;
}
return NULL;
}
strchr的实现
- 函数原型
char *MyStrchr(const char *dest, char c);
- 实现代码
char *MyStrchr(const char *dest, char c)
{
assert(dest);
while (*dest)
{
if (*dest == c)
{
return dest;
}
dest++;
}
return NULL;
}
strcmp的实现
- 函数原型
int MyStrcmp(const char *str1, const char *str2);
- 实现代码
int MyStrcmp(const char *str1, const char *str2)
{
assert(str1 && str2);
while (*str1 == *str2&&*str1 != '\0') //优化版本
{
str1++;
str2++;
}
if (*str1 == '\0'&&*str2 == '\0')
{
return 0;
}
else if (*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
/*while (*str1 != '\0'&&*str2 != '\0') //正常思路
{
if (*str1 > *str2)
{
return 1;
}
else if (*str1 < *str2)
{
return -1;
}
str1++;
str2++;
}
if (*str1 == '\0'&&*str2 == '\0')
{
return 0;
}
else if (*str1 == '\0')
{
return -1;
}
return 1;*/
}
memcpy的实现
- 函数原型
void *MyMemcpy(void *dest, const void *src,size_t size);
- 实现代码
//size表示字节数,此函数可实现任意类型,例如字符数组、整型、结构体、类等
void *MyMemcpy(void *dest, const void *src,size_t size)
{
assert(dest&&src);
char* tmp = (char *)dest;
while (size--)
{
*tmp++ = *((char *)src)++;
}
return dest;
}
memmove的实现
- 函数原型
void *MyMemmove(const void *deststr, const void *srcstr, size_t size);
- 实现代码
//考虑了内存重叠问题
void *MyMemmove(const void *deststr, const void *srcstr, size_t size)
{
assert(deststr&&srcstr);
if (deststr == srcstr)
{
return deststr;
}
else if (deststr < srcstr||deststr >=(char *)srcstr+size)
{
char *dest = (char *)deststr;
char *src = (char *)srcstr;
while (size--)
{
*dest++ = *src++;
}
return deststr;
}
else //内存重叠,从后向前拷贝
{
char *dest = (char *)deststr+size-1; //注意:向后偏移size+1(即:区间长度)
char *src = (char *)srcstr + size-1;
while (size--)
{
*dest-- = *src--;
}
return deststr;
}
}
总结
strcpy和memcpy主要有以下3方面的区别:
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符”\0”才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
附加测试代码
/以 下 为 测 试 代 码/
#define TEST_HEADER printf("==========================%s==========================\n",__FUNCTION__)
void TestStrcpy()
{
TEST_HEADER;
char dest[10] = "abcdef";
printf("%s\n", MyStrcpy(dest, "hallo")); //正常输出
//printf("%s\n", MyStrcpy(dest+2, dest)); //不能处理内存重叠
}
void TestStrcmp()
{
TEST_HEADER;
char str1[10] = "abcdef";
char str2[10]="abcdef";
printf("dest:%s,src:%s\n",str1, str2);
printf("ret expect is 0,real is %d\n", MyStrcmp(str1, str2));
}
void TestStrcat()
{
TEST_HEADER;
char dest[10] = "abcde";
char src[5] = "fgh";
printf("dest:%s,src=%s\n", dest, src);
printf("dest expect is abcdefgh,actual is %s\n", MyStrcat(dest, src));
}
void TestStrchr()
{
TEST_HEADER;
char dest[10] = "abcdefghi";
printf("dest:%s\n", dest);
printf("dest expect is %p,actual is %p\n", &dest[4], MyStrchr(dest, 'e'));
}
void TestStrstr()
{
TEST_HEADER;
char dest[10] = "abcdefghi";
char src[4] = "fgh";
printf("dest:%s,src=%s\n", dest, src);
printf("dest expect is %p,actual is %p\n", &dest[5], MyStrstr(dest, src));
}
void TestMemcpy()
{
TEST_HEADER;
/*char dest[20] = "abcdefg";
char src[20] = "hello world!";
printf("dest:%s,src=%s\n", dest, src);
printf("dest expect is hello,actual is %s\n",MyMemcpy(dest, src,5));
*/
int dest[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int src[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
int i = 0;
MyMemcpy(dest, src, 10*sizeof(int));
for (i = 0; i < 10; i++)
{
printf("%d\t", dest[i]);
}
}
void TestMyMemmove()
{
TEST_HEADER;
char str1[20] = "hello world!";
char str2[20] = "hello world!";
char str3[20] = "hello world!";
MyMemmove(str1, str1 + 2, 5);
MyMemmove(str2+2, str2, 5);
MyMemmove(str3+2, str3, 2);
printf("str1 expect is llo w world! ,actual is %s\n", str1);
printf("str2 expect is hehelloorld! ,actual is %s\n", str2);
printf("str3 expect is heheo world! ,actual is %s\n", str3);
}
void TestStdio()
{
TEST_HEADER;
//char dest[20] = "abcdefg";
//char src[20] = "hello world!";
//printf("dest:%s,src=%s\n", dest, src);
//printf("dest expect is hello,actual is %s\n", memcpy(dest, src, 5));
/*int dest[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int src[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
int i = 0;
memcpy(dest, src, 4*sizeof(int));
for (i = 0; i < 10; i++)
{
printf("%d\t", dest[i]);
}
printf("\n");*/
char str1[20] = "hello world!";
char str2[20] = "hello world!";
char str3[20] = "hello world!";
memmove(str1, str1 + 2, 5);
memmove(str2 + 2, str2, 5);
memmove(str3 + 2, str3, 2);
printf("str1 expect is llo w world! ,actual is %s\n", str1);
printf("str2 expect is hehelloorld! ,actual is %s\n", str2);
printf("str3 expect is heheo world! ,actual is %s\n", str3);
}
int main()
{
TestStrcpy();
TestStrcmp();
TestStrcat();
TestStrchr();
TestStrstr();
TestMemcpy();
TestMyMemmove();
TestStdio();
system("pause");
return 0;
}