zoukankan      html  css  js  c++  java
  • 基于标准库的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(...)) 表示如果比较两者不相等!

  • 相关阅读:
    mysql分表和表分区详解
    CNN 文本分类
    基于深度学习的目标检测研究进展
    标注工具
    在Ubuntu登陆界面输入密码之后,黑屏一闪后,又跳转到登录界面
    R-CNN,SPP-NET, Fast-R-CNN,Faster-R-CNN, YOLO, SSD系列深度学习检测方法梳理
    LeNet,AlexNet,GoogleLeNet,VggNet等网络对比
    nginx使用与配置入门指南
    CentOS 7上重新编译安装nginx
    酸汤肉沫豆腐
  • 原文地址:https://www.cnblogs.com/Harley-Quinn/p/5405875.html
Copyright © 2011-2022 走看看