淘宝面试题:
已知strcpy函数的原型是:
char *strcpy(char *dst, const char *src);
1:实现strcpy函数;
2:解释为什么返回char *;
3: 假如考虑dst和src内存重叠情况,strcpy如何实现;
原始代码:
char *my_strcpy(char *dst,const char *src)
{
char *ret = dst;
while(*src != '\0')
{
*dst++ = *src++;
}
*dst = '\0';
return ret;
}
改进代码:
char *my_strcpy(char *dst,const char *src)//1
{
assert(dst != NULL && src != NULL);//2
char *ret = dst;//3
while((*dst++ = *src++) != '\0');
return ret;
}
//1:使用const,保证源字符串不被改变
//2:检查指针的有效性,增强代码的健壮性,使用NULL(拼写错误,编译器容易检查出来),而非0,增强程序的可维护性
//3:保存目标字符串的地址,程序结束时返回
//返回char*:使函数能够支持链式表达式:如:int lenth = strlen(strcpy(dst,src));
考虑内存重叠:
char *my_memmove(char *dst,const char *src,size_t lenth)
{
assert(dst != NULL && src != NULL);
char *ret = dst;
if(dst<src || dst>=src+lenth)//正常情况,从低地址往高地址依次拷贝
{
while(lenth--)
{
*dst++ = *src++;
}
}
else//内存重叠情况,从高地址往低地址拷贝
{
dst = dst + lenth - 1;//要存放元素的最后一个位置
src = src + lenth - 1;//最后一个要拷贝的元素的地址
while(lenth--)
{
*dst-- = *src--;
}
}
return ret;
}
//考虑内存重叠----my_strcpy
char *my_strcpy(char *dst,const char*src)
{
assert(dst != NULL && src != NULL);
char *ret = dst;
my_memmove(dst,src,strlen(src)+1);
return ret;
}
查看memmove函数原型:
void *my_memmove(void *dst,const void *src,size_t lenth)
实现如下:
void *my_memmove(void *dst,const void *src,size_t lenth)
{
assert(dst != NULL && src != NULL);
void *ret = dst;
char *dst1;//保存目标数组:强制转化类型后的地址
char *src1;// 保存源数组:强制转化类型后的地址
if((unsigned char *)dst<(unsigned char *)src
||(unsigned char *)dst>=((unsigned char *)src+lenth))
{
dst1 = (char *)dst;
src1 = (char *)src;
while(lenth--)
{
*dst1++ = *src1++;
}
}
else
{
dst1 = (char *)dst + lenth - 1;//问题?????????
src1 = (char *)src + lenth - 1;
while(lenth--)
{
*dst1-- = *src1--;
}
}
return ret;
}
问题:
dst1 = (char *)dst + lenth - 1;不应该指向最后一个空间之后,再强制类型转化么,如
int a[2] a+2-1指向最后一个空间,(char*)a+2-1并未指向最后一个空间,可是改成
(char*)(dst + lenth - 1);由于dst类型是void,无法加lenth,,那该怎么解决呢????
希望得到你们的解答,谢谢