题目:将某一字符串中的某段子串替换成新的字串,要求是原址(在源串上替换)替换,源串自己保证长度以便容纳新的字串。
例:
将 abcdefcdef 中的 c替换成gg,替换后的字符串:abggdefggef ;
或将cde替换成a,替换后的字符串:abafaf。
代码:
/************************************************************************/
/*
函数功能:用新子串替换源字符串中的子串(原址替换)
说明:新串比旧串长时,需保证源buf足够容纳替换后的字符串
*/
/************************************************************************/
bool STR_Replace(char *szBuf,uint uiBufLen,char *oldStr,char *newStr)
{
uint uiOldLen = 0;
uint uiNewLen = 0;
uint uiDstIndex = 0;
uint uiLen = 0;
char *pcLast = NULL;
char *pcCurCursor = NULL;
if ((NULL == szBuf) || (NULL == oldStr) || (NULL == newStr) || (uiBufLen<=0))
{
printf("Invalid inputs.p1(%p),p2(%u),p3(%p),p4(%p).",szBuf,uiBufLen,oldStr,newStr);
return false;
}
uiOldLen = strlen(oldStr);
uiNewLen = strlen(newStr);
/* 旧串不能为空,新串可以为空 */
if (0 == uiOldLen)
{
printf("Old str(%s) should not be null !",oldStr);
return false;
}
if (uiNewLen > uiOldLen)
{
/* 新串比旧串长(扩展替换) */
return STR_Expand_Replace(szBuf,uiBufLen,oldStr,newStr);
}
else
{
/* 新串比旧串短 */
pcLast =szBuf;
pcCurCursor = strstr(pcLast,oldStr); //寻找旧子串第一次出现的位置
while ((NULL != pcCurCursor) && (uiDstIndex < uiBufLen))
{
uiLen = (uint)(pcCurCursor - pcLast);
memcpy(szBuf+uiDstIndex,pcLast,uiLen); //拷贝uiLen个长
memcpy(szBuf+uiDstIndex+uiLen,newStr,uiNewLen);//拷贝新串
uiDstIndex += (uiLen+uiNewLen); //下次拷贝的起点(上面已经拷贝了uiLen+uiNewLen长)
pcLast = pcCurCursor + uiOldLen; //搜索下一个子串的起点
pcCurCursor = strstr(pcLast,oldStr); //定位下一个待替换子串位置
}
// strcpy(szBuf+uiDstIndex , pcLast,uiBufLen - uiDstIndex); //拷贝最末尾一段
memcpy(szBuf+uiDstIndex , pcLast,uiBufLen - uiDstIndex);
}
return true;
}
/************************************************************************/
/*
函数功能:用新子串替换源字符串中的子串(原址替换 新字串比旧字串长)
*/
/************************************************************************/
bool STR_Expand_Replace(char *szBuf,uint uiBufLen,char *oldStr,char *newStr)
{
uint uiSrcStrLen = 0;
uint uiOldLen =0;
uint uiNewLen =0;
uint uiCnt =0; //记录旧字串出现的次数
uint uiPartLen = 0;
char *pcCurCursor = NULL;
uint auiIndex[SUBSTR_MAX_CNT] = {0}; //保存每次查找到的字串的位置
if ((NULL == szBuf) || (NULL == oldStr) || (NULL == newStr) || (uiBufLen <=0))
{
printf("Invalid inputs.p1(%p),p2(%u),p3(%p),p4(%p).",szBuf,uiBufLen,oldStr,newStr);
return false;
}
uiSrcStrLen = strlen(szBuf);
uiOldLen = strlen(oldStr);
uiNewLen = strlen(newStr);
assert(uiNewLen > uiOldLen);
pcCurCursor = strstr(szBuf,oldStr);
while((NULL != pcCurCursor) && (uiCnt < SUBSTR_MAX_CNT))
{
auiIndex[uiCnt++] = (uint)(pcCurCursor- szBuf);
//查找下一个旧字串位置
pcCurCursor = strstr(pcCurCursor + uiOldLen,oldStr);
}
if ((NULL != pcCurCursor) && (uiCnt >= SUBSTR_MAX_CNT))
{
printf("Old str occur too many times :(%u)\n",uiCnt); //旧字串出现次数太多
return false;
}
if (uiSrcStrLen + (uiNewLen-uiOldLen)*uiCnt > uiBufLen)
{
/* 源buf不足以容纳替换后的字符串 */
printf("SrcBuf cannot accommodata Newstr !\n");
return false;
}
auiIndex[uiCnt] = uiSrcStrLen;
pcCurCursor = szBuf+uiSrcStrLen+(uiNewLen-uiOldLen)*uiCnt ; //定位到末尾
*pcCurCursor = '\0'; //加上末尾标识
for (int i = uiCnt;i>0;--i)
{
uiPartLen = (auiIndex[i]-auiIndex[i-1])-uiOldLen; //找到源串末尾部分段长(不包括旧串)
pcCurCursor -= uiPartLen;
//移动源串末尾部分段(不包括旧串)
memmove(pcCurCursor,szBuf+auiIndex[i-1]+uiOldLen,uiPartLen);
//定位新串插入的位置
pcCurCursor -= uiNewLen;
//插入新串
memcpy(pcCurCursor,newStr,uiNewLen);
}
pcCurCursor -= auiIndex[0]; //最后的pcCurCursor
return true;
}
/************************************************************************/
/*
字符串替换测试函数
*/
/************************************************************************/
void test_str_replace_fun()
{
char pSrcStr[200] = "abcdefgbcg";
char pOldStr_1[4]="bc";
char pOldStr_2[2]="g";
char pNewStr_1[2]="z"; //把bc替换成z
char pNewStr_2[4]="opq"; //把g替换成opq
printf("The src str : \n");
printf("%s",pSrcStr);
if(STR_Replace(pSrcStr,200,pOldStr_1,pNewStr_1))
{
printf("\nThe first replace(%s--%s) : \n",pOldStr_1,pNewStr_1);
printf("( %s )\n",pSrcStr);
if (STR_Replace(pSrcStr,200,pOldStr_2,pNewStr_2)) //失败 再测
{
printf("\nThe Second replace(%s--%s) : \n",pOldStr_2,pNewStr_2);
printf("( %s )\n",pSrcStr);
}
}
return ;
}
简单说明:
通过pcCurCursor定位,每次替换(移动)源字符串中的一段。当新子串比旧子串长时,源串自己保证自己的buf足够大,且旧子串在源串中出现的次数不宜过多(这也满足绝大部分应用)。不懂的可以自己按照while循环执行步骤动手画画。
测试结果: