IE盒子

搜索
查看: 140|回复: 0

c++ STL替换算法:replace()、replace_if()、replace_copy ...

[复制链接]

1

主题

2

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2023-1-13 19:02:58 | 显示全部楼层 |阅读模式

主要函数有:

  • replace():用一个给定值替换一些值。
  • replace_if():替换满足谓词的一些元素。
  • replace_copy():复制序列时用一给定值替换元素。
  • replace_copy_if():复制序列时替换满足谓词的元素。
replace函数模板的行为等同于:

template <class ForwardIterator, class T>
  void replace (ForwardIterator first, ForwardIterator last,
                const T& old_value, const T& new_value)
{
  while (first!=last) {
    if (*first == old_value) *first=new_value;
    ++first;
  }
}前两个参数是被处理序列的前向迭代器,第 3 个参数是被替换的值,第 4 个参数是新的值。遍历容器序列,若某元素等于旧值,则用新值代替。
例子:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int a[9] = {1, 2, 3, 4, 5, 4, 3, 2, 1};
    cout<< "原始数据: ";
    copy(a, a + 9, ostream_iterator<int>(cout, " "));
    cout<< endl;
   
    cout<< "原数据2用10代替(replace): ";
    vector<int> v1(a, a + 9);
    replace(v1.begin(), v1.end(), 2, 10);
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout<< endl;
}

replace_if函数模板的行为等同于:

template < class ForwardIterator, class UnaryPredicate, class T >
  void replace_if (ForwardIterator first, ForwardIterator last,
                   UnaryPredicate pred, const T& new_value)
{
  while (first!=last) {
    if (pred(*first)) *first=new_value;
    ++first;
  }
}其中第 3 个参数是一个谓词,第 4 个参数是新的值。参数的类型一般是元素类型的 const 引用;const 不是强制性的,但谓词不应该改变元素。
例子:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int a[9] = {1, 2, 3, 4, 5, 4, 3, 2, 1};
    cout<< "原始数据: ";
    copy(a, a + 9, ostream_iterator<int>(cout, " "));
    cout<< endl;
   
    cout<< "原数据<4用20代替(replace_if): ";
    vector<int> v1(a, a + 9);
    replace_if(v1.begin(), v1.end(), bind2nd(less<int>(), 4), 20);
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout<< endl;
}

replace_copy函数模板的行为等同于:

template <class InputIterator, class OutputIterator, class T>
  OutputIterator replace_copy (InputIterator first, InputIterator last,
                               OutputIterator result, const T& old_value, const T& new_value)
{
  while (first!=last) {
    *result = (*first==old_value)? new_value: *first;
    ++first; ++result;
  }
  return result;
}replace_copy() 算法和 replace() 做的事是一样的,但它的结果会被保存到另一个序列中,而不会改变原始序列。它的前两个参数是输入序列的正向迭代器,第 3 个参数是输入序列的开始迭代器,最后两个参数分别是要被替换的值和替换值。
例子:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int a[9] = {1, 2, 3, 4, 5, 4, 3, 2, 1};
    cout<< "原始数据: ";
    copy(a, a + 9, ostream_iterator<int>(cout, " "));
    cout<< endl;
   
    cout<< "原数据4用30代替(replace_copy): ";
    vector<int> v1(a, a + 9);
    vector<int> v2;
    replace_copy(v1.begin(), v1.end(), back_inserter(v2), 4, 30);
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " "));
    cout<< endl;
}

replace_copy_if函数模板的行为等同于:

template <class InputIterator, class OutputIterator, class UnaryPredicate, class T>
  OutputIterator replace_copy_if (InputIterator first, InputIterator last,
                                  OutputIterator result, UnaryPredicate pred,
                                  const T& new_value)
{
  while (first!=last) {
    *result = (pred(*first))? new_value: *first;
    ++first; ++result;
  }
  return result;
}当然replace_copy_if() 和 replace_if() 算法是相同的,但它的结果会被保存到另一个序列中。它的前两个参数是输入序列的迭代器,第 3 个参数是输出序列的开始迭代器,最后两个参数分别是谓词和替换值。
例子:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int a[9] = {1, 2, 3, 4, 5, 4, 3, 2, 1};
    cout<< "原始数据: ";
    copy(a, a + 9, ostream_iterator<int>(cout, " "));
    cout<< endl;
   
    cout<< "原数据<4用40代替(replace_copy_if): ";
    vector<int> v1(a, a + 9);
    vector<int> v2;
    replace_copy_if(v1.begin(), v1.end(), back_inserter(v2), bind2nd(less<int>(), 4), 30);
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " "));
    cout<< endl;
}

一个replace易犯的一个错误:
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
int main(){
    int a[] = {2, 1, 3, 2, 2, 5};
    cout<< "原始数据: ";
    copy(a, a + 6, ostream_iterator<int>(cout, " "));
    cout<< endl;
   
    replace(a, a + 6, a[0], 10);
    copy(a, a + 6, ostream_iterator<int>(cout, " "));
    cout<< endl;
}

这看起来是一个非常简单的例子,完成的功能是把数组a[]中所有整型数2用10来代替。但结果却是“10 1 3 2 2 5”,仅第一个2变成了10,这是什么原因呢?
看一下replace的定义,就能容易发现原因:
void replace (Fwdit first,FwdIt last,const T & vold,const T & vnew)vold参数是引用调用,而非传值调用。对本例而言,初始时vold=2,按表意形式相当于replace(a,a+6,2,10),但当第一次发现数组中元素⒉,恰好是a[0],这样a[o]就变成10。由于是引用调用,相当于vold=10,这样当继续扫描数组a时,按表意形式相当于replace(a+1,a+6,10,10),因为 vold=vnew=10,所以α数组后续元素不可能再发生变化。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表