基于标准库的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会生成新的字符串。
要点5:compare在两者相等时返回0!即if (compare(...)) 表示如果比较两者不相等!
基于标准库的string类实现简单的字符串替换的更多相关文章
- 基于标准库实现string和wstring的转换
// convert string to wstring std::wstring to_wstring(const std::string& str, const std::locale&a ...
- C++ 标准库类型-String,Vector and Bitset
<C++ Primer 4th>读书摘要 最重要的标准库类型是 string 和 vector,它们分别定义了大小可变的字符串和集合.这些标准库类型是语言组成部分中更基本的那些数据类型(如 ...
- 谈谈两种标准库类型---string和vector
两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库 ...
- C++ Primer 第三章 标准库类型string运算
1. 标准库类型 string string表示可变长的字符序列,使用string必须首先包含string头文件.如何初始化类的对象是由类本身决定的. int n; string s1;//默认初始化 ...
- 标准C++中string类的用法
转自博客园:http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html 相信使用过MFC编程的朋友对CString这个类的印象应该非 ...
- 彻底弄清c标准库中string.h里的常用函数用法
在我们平常写的c/c++程序,一些算法题中,我们常常会用到c标准库中string.h文件中的函数,这些函数主要用于处理内存,字符串相关操作,是很有用的工具函数.而且有些时候,在笔试或面试中也会出现让你 ...
- 标准C++的string类使用
原文:http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html 要想使用标准C++中string类,必须要包含#include & ...
- 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/ [在此向原文作者说声谢谢!若有读者看到文章转载时请写该转载地址 ...
- 标准C++中string类的用法总结
相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...
随机推荐
- LeetCode OJ:Climbing Stairs(攀爬台阶)
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...
- 【ecmascript】Javascript 严格模式详解【转】
一.概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode).顾名思义,这种模式使得Javascript在更严格的条件下运行. ...
- 建造者模式(Builder和Director)
一.建造者模式介绍 建造者模式:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. [构建与表示分离,同构建不同表示] 假如一个对象的构建很复杂,需要很多步骤.则可以使用建造者模式 ...
- ios 第3天
在手动引用计数中 每一次调用 retain retainCount 就会加一 每一次release retainCount就会减一 当retainCount 为零时 就会free (p) ; ...
- java与mysql时间类型对应的问题
项目中遇到一个问题,从后台给出的json字符串中取得的时间,之后通过方法转换成 yyyy-MM-dd hh:mm:ss 的时候,转换后的得到的竟然是1969年...之后排查问题: 发现了在mayba ...
- L154
Several possessions of the late physicist's Stephen Hawking will be included in an upcoming auction ...
- 编译安装pgbouncer-checking for OpenSSL... configure: error: not found
花了一上午时间将pgbouncer的参数通读了一遍,对他有个大致的了解:1.配置分为连接池和pgbouncer两个部分[database]\[pgbouncer ].2.一条记录对应创建一个连接池,连 ...
- Android.mk编译的写法
更多Android.mk的 用法见 :http://blog.csdn.net/fengbingchun/article/details/38705519 如何修改Android.mk 为Androi ...
- 浅谈OSSemPost()和OSSemPend()
http://blog.csdn.net/goodman_lqifei/article/details/53616174
- PHPStorm 使用正则批量查询替换并自动转换大小写的方法
PHPStorm 的项目查询替换功能那是非常非常强大的, 速度也很快, 配合正则更加灵活强大. 一般的正则查询替换没什么太多好说的, 这里主要说说比较少用的 大小写自动转换的问题, 也是比较少用但很有 ...