替换字符串中连续出现的指定字符串

题目:

给定单个字符串str、from和to,已知from字符串中无重复字符,把str中所有from的子串全部替换成to字符串,对连续出现from的部分要求只替换成一个to字符串,返回最终结果字符串。

举例:

str="123abc",from="abc",to="4567",返回"1234567";

str="123",from="abc",to="4567",返回"123";

str="123abcabc",from="abc",to="X",返回"123X";

难度:

思路:

应该有好久没做题了。。。。。做一题都要debug好多次,说明刚开始构思的时候,就没能把问题的边界情况考虑全面。

在这里要特别注意,对于字符串的处理,一定要考虑到字符串的边界问题,有可能因为遍历结束前的子串只是记录,并没有做出相应处理!!!

现在每次看到字符串的题目,就要求自己必须使用单个循环,虽然现在处理地还是比较丑,但慢慢来嘛~~~

大概思路是先指向from字符串的首地址,遍历整个字符串,若from当前字符与str当前字符相等,相应的相同子串长度flag自增,from子串下标自增;若不相等,则进行一系列判断。。。实在太多,就在代码中写吧。。。

代码:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string str, from, to, nstr;
	getline(cin, str);
	getline(cin, from);
	getline(cin, to);
	int len = str.size(), flen = from.size(), tlen = to.size();
	int i, j = 0, flag = 0, already = 0;
	for (i = 0; i < len; i++)
	{
		if (str[i] == from[j]&&j != flen) // 对应字符相等且未遍历完字符串from
		{
			flag++; j++;
		}
		else                              // 对象字符不等
		{
			if (flag == flen&&already == 0)   // 相同子串长度flag等于from字符串长度且之前没有出现相同from字符串
			{
				nstr += to;                   // 替换成to字符串
				already = 1;                  // 将already置为1,表示出现相同from字符串
			}
			else if (flag != flen)            // 相同子串长度flag不等于from字符串长度
			{
				if (flag)                     // 如果有相同子串
				{	
					nstr += str.substr(i - flag, flag);
				}
				else                          // 如果没有相同子串,则仅把当前字符添加在nstr后
					nstr += str[i];
			}
			flag = 0;                         // 将flag和j置为0,下次从头开始比较
			j = 0;
			if (str[i] == from[j])            // 注意,这里容易忽略!如果遇到当前字符相等,需要将各标志位自增
										      // 如:str="abcabcab",from="abc",在遍历到下标为3时,其实是下一个from字符串的开始
			{
				flag++;
				j++;
			}
		}
	}
	if (flag == flen&&already == 0)             // 对于遍历结束后的边界处理问题
		nstr += to;
	else
	{
		if (flag)
			nstr += str.substr(i - flag, flag);
		else
			nstr += str[i - 1];
	}
	cout << nstr << endl;
	system("pause");
	return 0;
}

参考思路:

书上的思路比较清晰,因为参考程序将字符串寻找from子串和生成替换后的字符串分开操作。

我的思路是一边判断,一边替换,很容易出错!所以,记住:查找和处理能分开操作就分开操作!

大致思路是把str看作字符类型的数组,首先把str中from部分所有位置的字符编码设为0(即空字符),如"12abcabca4",from="abc",处理后str=['1','2',0,0,0,0,0,0,'a','4']。

具体步骤如下,

1 生成整数变量match,标识目前匹配到from字符串的什么位置,初始时match=0;

2 从左到右遍历str中每个字符,假设当前遍历到str[i];

3 若str[i]==from[match],若match是from最后一个字符的位置,说明在str中发现了from字符串,则从i位置向前的M个位置,都把字符编码设为0,M为from的长度,设置完成后令match=0;若match不是from最后一个字符的位置,则match++。继续遍历str的下一个字符;

4 若str[i]!=from[match],说明匹配失败,令match=0,即回到from开头重新匹配。继续遍历str的下一个字符;

参考代码:

#include <iostream>
#include <string>
using namespace std;
void clear(char* str, int end, int len)
{
	int i;
	for (i = 0; i < len; i++)
		str[end - i]='.';   // 不能像书中设为0,否则0之后的字符串都不会读取,因为0是作为字符串的空字符'\0'
}
int main()
{
	string str, from, to, nstr;
	char p[100];            // 不能定义为char* p;,因为p在没有明确指向某个内存空间就使用,会报错
	getline(cin, str);
	getline(cin, from);
	getline(cin, to);
	strcpy(p, str.c_str()); // 将string类型转换成char数组
	int len = str.size(), flen = from.size(), tlen = to.size();
	if (len == 0 || flen == 0 || tlen == 0)
	{
		cout << str << endl;
		return 0;
	}
	int i, match = 0;
	for (i = 0; i < len; i++)
	{
		if (str[i] == from[match])
		{
			if ((match+1) == flen)
			{
				clear(p, i, flen);
				match = 0;
			}
			else
			{
				match++;
			}
		}
		else
			match = 0;
	}
	for (i = 0; i < len; i++)
	{
		if (p[i] != '.')
			nstr += p[i];
		else if (p[i] == '.' && (i == 0 || p[i - 1] != '.'))
		{
			nstr += to;
		}
	}
	cout << nstr << endl;
	system("pause");
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值