基于标准库的string类实现简单的字符串替换

感觉基本功还是不扎实,虽然能做些程序但是现在看来我还是个初学者(primer),试着完成习题结果还得修修改改。

废话不多说,实现功能很简单,《C++ Primer》9.5.2节习题。

// 将s中所有oldVal替换成newVal
void replace(string& s, const string& oldVal, const string& newVal);

对字符串进行替换,实际上是先找到字符串s中的匹配部分,将匹配部分(oldVal)删除,然后插入要替换的字符串(newVal)

std::string的成员函数有很多重载形式,但总结下来是用两种方式表示区间:(pos, n)和(b, e)

都是左开右闭,前者是从pos开始的n个字符,后者则是两个迭代器之间的字符串。

因此关于进行匹配的字符串,可以用s.substr(pos, n)表示截取字符串,或者用string(b, e)来构造新的字符串。

要点1:由于是左开右闭,所以如果用迭代器遍历,用iter != s.end()来判断,会漏掉末尾。(比如用abc来替换ab时,字符串abcab会被变成abccab,而本该是变成abccabc)。

要点2也不要用iter <= s.end()判断,因为循环语句内部的逻辑是,没找到匹配字符串时++iter,那么再次判断结束循环条件就会出问题。

(比如判断s.begin() + 1 + s.size() <= s.end(),相当于判断s.end() + 1 <= s.end())

总结上述要点,用迭代器遍历不能像下标遍历那样用<=来判断。

要点3迭代器和下标的变化。如果没有匹配到字符串只需要自加就行,但是匹配到后,进行删除和插入后,无论是迭代器还是下标都是左开右闭的“开”这个位置,所以需要移到“闭”这个位置,以免无限循环。(比如把ab替换成abc后,应该从c后面一个字符开始查找,而不对位置做操作时会再在a的位置查找)

以上就是我试写程序时遇到的几个错误,下面贴代码。

第一题是用到std::string的insert和erase函数。我使用了迭代器遍历

// 使用迭代器及insert和erase将s中所有oldVal替换成newVal
void replace(string& s, const string& oldVal, const string& newVal)
{
	auto iter = s.begin();
	size_t oldSize = oldVal.size();
	size_t newSize = newVal.size();
	while (iter + oldSize < s.end())
	{
		if (string(iter, iter + oldSize) == oldVal)
		{
			iter = s.erase(iter, iter + oldSize);
			iter = s.insert(iter, newVal.cbegin(), newVal.cend());
			iter += newSize;
		}
		else
			++iter;
	}
	// 判断最后一个字符串是否等于oldVal
	if (string(iter, iter + oldSize) == oldVal)
	{
		s.erase(iter, iter + oldSize);
		s.insert(iter, newVal.cbegin(), newVal.cend());
	}
}

第二题是直接用replace函数。我使用了下标遍历。

void replace(string& s, const string& oldVal, const string& newVal)
{
	size_t oldSize = oldVal.size();
	size_t newSize = newVal.size();
	string::size_type i = 0;
	while (i <= s.size() - oldSize)
	{
		if (s.substr(i, oldSize) == oldVal)
		{
			// 进行替换
			s.replace(i, oldSize, newVal);
			// 更改当前位置
			i += newSize;
		}
		else
			++i;
	}
}

要点4每次进行替换字符串的长度会变化

刚才我就是在这里出错,因为我直接用size_t len = s.size();然后循环条件就是 i <= len - oldSize,想要代码看起来更清晰,实际上忽略了这点。

补充点:string提供了compare函数来专门和一对(pos, n)进行比较

比如s.substr(i, oldSize) == oldVal可以改成!s.compare(i, oldSize, oldVal)或s.compare(i, oldSize, oldVal) == 0,截取的字符串仅仅是用来比较的话还是用compare比较好,substr会生成新的字符串。

要点5compare在两者相等时返回0!即if (compare(...)) 表示如果比较两者不相等!

原文地址:https://www.cnblogs.com/Harley-Quinn/p/5405875.html