如题:将字符串src逆序后,经过输出参数dest返回给调用方。函数原型如下:
bool convertString(char *dest,const char*src,int destBufSize)
偶在一次面试中遇到此题,奋笔疾书写作如下:
bool convertString(char *dest,const char *src,size_t destBufSize)
{
if(dest == NULL || src == NULL)
return false;
size_t srclen = strlen(src);
if(srclen > destBufSize)
return false;
char *pDest = dest;
for(size_t i = 0;i< srclen;i++)
{
pDest[i] = src[srclen -i -1];
}
pDest[srclen] = '\0';
return true;
}
结果别人写测试程序,我一看傻眼了,
char Src[100] = {0};
char Dest[100] = {0};
strcpy(Src,"abcdefghijklnmopqrstuvwxyz");
convertString(Src,Src,sizeof(Src));
很显然上面的convertString无法处理此种情况,结果会是字符串后半部分回文2次,前半部分字符串丢失,但是函数返回true。
可以看出上述函数存在很大的问题,我们来具体分析一下:
如果src地址为最上面的那个横线,则分如下几种情况传dest进来
1、src与dest相互不重叠
2、src与dest地址有一部分重叠
3、src与dest地址完全重叠(包含在第二种情况中)
此时我们需要改变算法,地址不重叠的部分使用字符串拷贝赋值的方式逆转,地址重叠的部分需要进行字符串交换。
于是形成了我们新的程序:
void swap(char *src ,size_t size)
{
if(src == NULL )
return ;
size_t len = strlen(src);
if( size > len)
return ;
char temp ;
for(size_t i = 0;i<(size/2);i++)
{
temp = src[i];
src[i] = src[size - i -1];
src[size -i -1] = temp;
}
}
bool convertString(char *dest,const char *src,size_t destBufSize)
{
if(dest == NULL || src == NULL)
return false;
size_t srclen = strlen(src);
if(destBufSize < srclen)
return false;
char *pTempDest = dest;
if(dest>=src && dest < src + srclen)
{
int destPos = dest - src;
char *pTemp = dest+srclen-destPos;
swap(pTemp,srclen - destPos);
for(int i = 0;i<destPos;i++)
{
pTempDest[srclen - i -1] = src[i];
}
pTempDest[srclen] = '\0';
}
else if(dest < src && dest + srclen > src)
{
int srcPos = src - dest;
char *pTemp = dest + srcPos;
swap(pTemp,srclen - srcPos);
for(int i = 0;i<srcPos;i++)
{
pTempDest[i] = src[srclen - i -1];
}
pTempDest[srclen] = '\0';
}
else
{
for(int i = 0;i< srclen;i++)
{
pTempDest[i] = src[srclen - i - 1];
}
}
pTempDest[srclen]='\0';
return true;
}
此程序经过测试,与预期的结果一致。但是时间仓促没有仔细推敲里面实现的细节,代码质量不好。
当然这个转换函数是尽最大的期望逆转成功,还有一种方法就是查看地址,如果地址有重叠时,直接返回false,反正src为const类型的,用户可能期望不要更改源地址内容的,呵呵,这样程序就比较简单了:
bool convertString(char *dest,const char *src,size_t destBufSize)
{
if(dest == NULL || src == NULL)
return false;
size_t srclen = strlen(src);
if(destBufSize < srclen)
return false;
if((dest >=src && dest < src + srclen)
|| (dest < src && dest + destBufSize > src ))
return false;
char *pDest = dest;
for(size_t i = 0;i< srclen;i++)
{
pDest[i] = src[srclen -i -1];
}
pDest[srclen] = '\0';
return true;
}