感觉基本功还是不扎实,虽然能做些程序但是现在看来我还是个初学者(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(...)) 表示如果比较两者不相等!

基于标准库的string类实现简单的字符串替换的更多相关文章

  1. 基于标准库实现string和wstring的转换

    // convert string to wstring std::wstring to_wstring(const std::string& str, const std::locale&a ...

  2. C++ 标准库类型-String,Vector and Bitset

    <C++ Primer 4th>读书摘要 最重要的标准库类型是 string 和 vector,它们分别定义了大小可变的字符串和集合.这些标准库类型是语言组成部分中更基本的那些数据类型(如 ...

  3. 谈谈两种标准库类型---string和vector

    两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...

  4. C++ Primer 第三章 标准库类型string运算

    1. 标准库类型 string string表示可变长的字符序列,使用string必须首先包含string头文件.如何初始化类的对象是由类本身决定的. int n; string s1;//默认初始化 ...

  5. 标准C++中string类的用法

    转自博客园:http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html 相信使用过MFC编程的朋友对CString这个类的印象应该非 ...

  6. 彻底弄清c标准库中string.h里的常用函数用法

    在我们平常写的c/c++程序,一些算法题中,我们常常会用到c标准库中string.h文件中的函数,这些函数主要用于处理内存,字符串相关操作,是很有用的工具函数.而且有些时候,在笔试或面试中也会出现让你 ...

  7. 标准C++的string类使用

    原文:http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html 要想使用标准C++中string类,必须要包含#include & ...

  8. C 和 C++ 的标准库分别有自己的 locale 操作方法,C 标准库的 locale 设定函数是 setlocale(),而 C++ 标准库有 locale 类和流对象的 imbue() 方法(gcc使用zh_CN.GBK,或者zh_CN.UTF-8,VC++使用Chinese_People's Republic of China.936或者65001.)

    转自:http://zyxhome.org/wp/cc-prog-lang/c-stdlib-setlocale-usage-note/ [在此向原文作者说声谢谢!若有读者看到文章转载时请写该转载地址 ...

  9. 标准C++中string类的用法总结

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...

随机推荐

  1. vue组件间传值

    父传子 1.父组件:在子组件容器内绑定数据 <router-view :unusedOrderNum="num1" :usedOrderNum="num2" ...

  2. [转载]Java导出Excel

    一.需求介绍 当前B/S模式已成为应用开发的主流,而在开发企业办公系统的过程中,常常有客户这样子要求:把系统数据库中的数据导出到Excel,用户查看报表时直接用Excel打开.或者是:用户已经习惯用E ...

  3. Nginx+keepalived 脚本安装主从双机热备自动切换解决方案

    Nginx+keepalived 脚本安装主从双机热备自动切换解决方案 2013-07-02 19:24:13 标签:filesnginx keepalived 原创作品,允许转载,转载时请务必以超链 ...

  4. compass框架的sprite雪碧图的用法简要

    ---恢复内容开始--- **简介** CSS SPRITE 即 CSS雪碧,即是将诸多图片合成一张图片,然后使用CSS 的background和background-position属性渲染. 这样 ...

  5. linux安装vmware出现Gtk-Message: Failed to load module pk-gtk-module canberra-gtk-module的解决方法

    使用此方法正确解决了问题, 文章地址如下: http://ian.wang/129.htm 为了防止以后看不到,特截图如下,希望博主不要怪罪.

  6. 剑指offer--51.表示数值的字符串

    正则好舒服, ------------------------------------------------------------------------------------------ 时间 ...

  7. shell脚本实例一

    一. 什么是shell 脚本时一种解释性语言: shell脚本保存执行动作: 脚本判定命令的执行条件 脚本来实现动作的批量执行.二.如何创建 vim  test.sh     ##shell脚本一般都 ...

  8. python中封装

    封装 引子 从封装的本身意思去理解,封装就是用一个袋子,把买的水果.书.水杯一起装进袋子里,然后再把袋子的口给封上,照这样的理解来说,封装=隐藏,但是,这种理解是片面的 ## 如何封装 在python ...

  9. UIview的一些属性

    一.UIView(视图\控件)1.在屏幕上能看得见.摸得着的东西,都是UIView对象2.任何UIView都可以充当其他UIView的容器3.关于UIView的一些疑问1> 谁来管理UIView ...

  10. Linux之Ubuntu

    1.1 使用创建用户登陆 Ubuntu 默认root用户无法登陆,只能使用在安装系统的时候新创建的用户登录 我这里新建的用户是ubuntu密码111111 1.2 安装ssh server 由于新建的 ...