字符串逆转隐藏的秘密

来源:互联网 发布:淘宝客超级搜索 编辑:程序博客网 时间:2024/04/30 13:14

如题:将字符串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;}


 

原创粉丝点击