感觉基本功还是不扎实,虽然能做些程序但是现在看来我还是个初学者(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. 【51nod-1010】因子只含有2 3 5的数

    K的因子中只包含2 3 5.满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15. 所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数. 例如:n = ...

  2. HDU 4704 Sum (隔板原理 + 费马小定理)

    Sum Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/131072K (Java/Other) Total Submiss ...

  3. GSpan-频繁子图挖掘算法

    GSpan频繁子图挖掘算法,网上有很多相关的介绍,中文的一些资料总是似是而非,讲的不是很清楚(感觉都是互相抄来抄去,,,基本都是一个样,,,),仔细的研读了原论文后,在这里做一个总结. 1. GSpa ...

  4. docker 快速搭建 WordPress

    安装Docker 环境:阿里云服务器 镜像:CentOs 7.4 64 https://docs.docker.com/install/linux/docker-ce/centos/ 安装WordPr ...

  5. 在创建一个MVC控制器,显示运行所选代码生成器时出错(带读写,使用EF)

    在创建一个MVC控制器,在Controllers文件夹选择添加->控制器,如下图: 显示运行所选代码生成器时出错 解决方法: 第一步:Install-Package Microsoft.aspn ...

  6. bfs+状态压缩dp

    题目连接 题解 : 对两两管道进行bfs,然后用dp[i][j] 来表示在i状态下通过了前j个管道 参考博客 #include<bits/stdc++.h> using namespace ...

  7. vue.js 源代码学习笔记 ----- instance state

    /* @flow */ import Dep from '../observer/dep' import Watcher from '../observer/watcher' import { set ...

  8. Makefile.am文件的实例讲解

    Makefile.am是一种比Makefile更高层次的编译规则,可以和configure.in文件一起通过调用automake命令,生成Makefile.in文件,再调用./configure的时候 ...

  9. OPEN(SAP) UI5 学习入门系列之一:扫盲与热身(上)

    什么是SAP Fiori? 了解SAP UI5必须要从SAP Fiori开始,两者概念经常被混淆,而两者也确实有着非常紧密的关系. 用过SAP的同学们都对SAP的传统的界面(SAP GUI)表示“呵呵 ...

  10. 高德地图Demo运行报错 com.android.ide.common.process.ProcessException: Failed to execute aapt

    最近由于有需求去做导航方面的Android开发,很是无奈,以前也的确是没有搞过,领导开大会当着所有人的面说这是给我分配的第一个工作,无论如何要做好,突然间感觉压力好大,自己已经多年没有敲过代码,而且A ...