字符串替换

题目:将某一字符串中的某段子串替换成新的字串,要求是原址(在源串上替换)替换,源串自己保证长度以便容纳新的字串。

例:

将 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循环执行步骤动手画画。

测试结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值