当前位置:   article > 正文

【C++】STL 算法 - transform 变换算法 ② ( 变换规则为 普通函数 | 变换规则为 Lambda 表达式 | 变换规则为 函数对象 | 变换规则为 函数适配器转换的函数对象 )

【C++】STL 算法 - transform 变换算法 ② ( 变换规则为 普通函数 | 变换规则为 Lambda 表达式 | 变换规则为 函数对象 | 变换规则为 函数适配器转换的函数对象 )





一、transform 算法



1、接收一个输入容器范围的 transform 算法函数原型


transform 算法函数原型 : 下面的函数原型作用是 将 一个输入容器 中的元素 变换后 存储到 输出容器 中 ;

template <class InputIt, class OutputIt, class UnaryOperation>  
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op);  
  • 1
  • 2
  • 参数解析 :
    • InputIt first1 参数 : 输入容器 的 起始迭代器 ( 包含 ) ;
    • InputIt last1 参数 : 输入容器 的 终止迭代器 ( 不包含 ) ;
    • OutputIt d_first 参数 : 输出容器 的 开始迭代器 , 输出元素个数 根据 输入元素 的 范围确定 , transform 会将 变换结果存储到 输出容器中 ;
    • UnaryOperation unary_op 参数 : 一元函数对象 , 将输入容器 的 每个元素 输入到该 一元函数对象 中 , 将计算结果 输出到 输出容器 中 ;
  • 返回值解析 :
    • 该 算法函数 返回 OutputIt 类型的 返回值是一个 迭代器 , 该迭代器指向最后一个被写入元素之后的位置 ;

2、代码示例 - 传入接受一个参数的普通函数


在下面的代码中 ,

首先 , 创建了一个 vector 数组容器 , 之后该容器 既作为输入容器 , 又作为输出容器 , 将元素输入后 , 计算后 , 在输出 到原来的容器中 ;

	// 创建一个 vector 数组容器
	vector<int> myVector;
  • 1
  • 2

然后 , 定义了一个 接受一个参数的 普通函数 , 使用该 函数 作为变换规则 ;

// 普通函数
int addone(int& n) {
	return ++n;
}
  • 1
  • 2
  • 3
  • 4

最后 , 将 myVector 数组容器的 元素范围 ( 起始迭代器 和 末尾迭代器 ) 作为输入容器 , 将 myVector 数组容器的 的 起始迭代器 作为输出容器 起始点 , 也就是 将 输入容器 的元素 进行修改 , 再次放回到 该容器中 ;

	// 向 transform 变换算法中 传入 普通函数
	transform(myVector.begin(), myVector.end(), myVector.begin(), addone);
  • 1
  • 2

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"

// 普通函数
int addone(int& n) {
	return ++n;
}

int main() {

	// 创建一个 vector 集合容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(9);
	myVector.push_back(5);
	myVector.push_back(2);
	myVector.push_back(7);

	// 向 transform 变换算法中 传入 一元函数对象
	transform(myVector.begin(), myVector.end(), myVector.begin(), addone);

	// 遍历容器
	for_each(myVector.begin(), myVector.end(), [](int element) {
		cout << element << endl;
	});

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

执行结果 :

10
6
3
8
请按任意键继续. . .
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述


3、代码示例 - 传入接受一个参数的 Lambda 表达式


在下面的代码中 ,

首先 , 创建了一个 vector 数组容器 , 之后该容器 既作为输入容器 , 又作为输出容器 , 将元素输入后 , 计算后 , 在输出 到原来的容器中 ;

	// 创建一个 vector 数组容器
	vector<int> myVector;
  • 1
  • 2

然后 , 定义了一个 接受一个参数的 Lambda 表达式 , 使用该 Lambda 表达式 作为变换规则 ;

// Lambda 表达式
[](int element) {
	return ++element;
}
  • 1
  • 2
  • 3
  • 4

最后 , 将 myVector 数组容器的 元素范围 ( 起始迭代器 和 末尾迭代器 ) 作为输入容器 , 将 myVector 数组容器的 的 起始迭代器 作为输出容器 起始点 , 也就是 将 输入容器 的元素 进行修改 , 再次放回到 该容器中 ;

	// 向 transform 变换算法中 传入 普通函数
	transform(myVector.begin(), myVector.end(), myVector.begin(), [](int element) {
		return ++element;
	});
  • 1
  • 2
  • 3
  • 4

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"

int main() {

	// 创建一个 vector 集合容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(9);
	myVector.push_back(5);
	myVector.push_back(2);
	myVector.push_back(7);

	// 向 transform 变换算法中 传入 Lambda 表达式
	transform(myVector.begin(), myVector.end(), myVector.begin(), [](int element) {
		return ++element;
	});

	// 遍历容器
	for_each(myVector.begin(), myVector.end(), [](int element) {
		cout << element << endl;
	});

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

执行结果 :

10
6
3
8
请按任意键继续. . .
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述


4、代码示例 - 传入接受一个 一元函数对象 作为变换规则


在下面的代码中 ,

首先 , 创建了一个 vector 数组容器 , 之后该容器 既作为输入容器 , 又作为输出容器 , 将元素输入后 , 计算后 , 在输出 到原来的容器中 ;

	// 创建一个 vector 数组容器
	vector<int> myVector;
  • 1
  • 2

然后 , 定义了一个 一元函数对象 , 使用该 一元函数对象 作为变换规则 ;

// 一元函数对象
class AddOne{
public:
	int operator()(int& n){
		return ++n;
	}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

最后 , 将 myVector 数组容器的 元素范围 ( 起始迭代器 和 末尾迭代器 ) 作为输入容器 , 将 myVector 数组容器的 的 起始迭代器 作为输出容器 起始点 , 也就是 将 输入容器 的元素 进行修改 , 再次放回到 该容器中 ;

	// 向 transform 变换算法中 传入 一元函数对象
	auto AD = AddOne();
	transform(myVector.begin(), myVector.end(), myVector.begin(), AD);
  • 1
  • 2
  • 3

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"

// 一元函数对象
class AddOne{
public:
	int operator()(int& n){
		return ++n;
	}
};

int main() {

	// 创建一个 vector 数组容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(9);
	myVector.push_back(5);
	myVector.push_back(2);
	myVector.push_back(7);

	// 向 transform 变换算法中 传入 一元函数对象
	auto AD = AddOne();
	transform(myVector.begin(), myVector.end(), myVector.begin(), AD);

	// 遍历容器
	for_each(myVector.begin(), myVector.end(), [](int element) {
		cout << element << endl;
	});

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

执行结果 :

10
6
3
8
请按任意键继续. . .
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述


5、代码示例 - 传入接受一个 STL 中预定义的 一元函数对象 作为变换规则


在下面的代码中 ,

首先 , 创建了一个 vector 数组容器 , 之后该容器 既作为输入容器 , 又作为输出容器 , 将元素输入后 , 计算后 , 在输出 到原来的容器中 ;

	// 创建一个 vector 数组容器
	vector<int> myVector;
  • 1
  • 2

然后 , 使用STL 中预定义的 一元函数对象 negate 作为变换规则 ; 该 预定义函数对象 源码如下 , 可以看到直接将输入参数 进行取反 操作 , 在前面加上一个符号 " - " 返回 ;

// STRUCT TEMPLATE negate
template <class _Ty = void>
struct negate {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty result_type;

    constexpr _Ty operator()(const _Ty& _Left) const {
        return -_Left;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

最后 , 将 myVector 数组容器的 元素范围 ( 起始迭代器 和 末尾迭代器 ) 作为输入容器 , 将 myVector 数组容器的 的 起始迭代器 作为输出容器 起始点 , 也就是 将 输入容器 的元素 进行修改 , 再次放回到 该容器中 ;

	// 向 transform 变换算法中 传入 预定义一元函数对象
	transform(myVector.begin(), myVector.end(), myVector.begin(), negate<int>());
  • 1
  • 2

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"

int main() {

	// 创建一个 vector 集合容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(-9);
	myVector.push_back(5);
	myVector.push_back(-2);
	myVector.push_back(7);

	// 向 transform 变换算法中 传入 预定义一元函数对象
	transform(myVector.begin(), myVector.end(), myVector.begin(), negate<int>());

	// 遍历容器
	for_each(myVector.begin(), myVector.end(), [](int element) {
		cout << element << endl;
	});

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

执行结果 :

9
-5
2
-7
请按任意键继续. . .
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述


6、代码示例 - 传入接受一个 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象


在下面的代码中 ,

首先 , 创建了一个 vector 数组容器 , 之后该容器 既作为输入容器 , 又作为输出容器 , 将元素输入后 , 计算后 , 在输出 到原来的容器中 ;

	// 创建一个 vector 数组容器
	vector<int> myVector;
  • 1
  • 2

然后 , 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象 ,

// 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象
bind2nd(multiplies<int>(), 10)
  • 1
  • 2

multiplies 函数对象源码如下 : 该函数对象的 重载 函数调用操作符 函数 , 接收 2 个参数 , 使用 bind2nd 函数适配器 为其设置第二个参数为 10 , 那么第一个参数就是 迭代器范围的 元素 ;

// STRUCT TEMPLATE multiplies
template <class _Ty = void>
struct multiplies {
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
    _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty result_type;

    constexpr _Ty operator()(const _Ty& _Left, const _Ty& _Right) const {
        return _Left * _Right;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

最后 , 将 myVector 数组容器的 元素范围 ( 起始迭代器 和 末尾迭代器 ) 作为输入容器 , 将 myVector 数组容器的 的 起始迭代器 作为输出容器 起始点 , 也就是 将 输入容器 的元素 进行修改 , 再次放回到 该容器中 ;

	// 向 transform 变换算法中 传入 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象
	transform(myVector.begin(), myVector.end(), myVector.begin(), bind2nd(multiplies<int>(), 10));
  • 1
  • 2

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"

int main() {

	// 创建一个 vector 集合容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(9);
	myVector.push_back(5);
	myVector.push_back(2);
	myVector.push_back(7);

	// 向 transform 变换算法中 传入 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象
	transform(myVector.begin(), myVector.end(), myVector.begin(), bind2nd(multiplies<int>(), 10));

	// 遍历容器
	for_each(myVector.begin(), myVector.end(), [](int element) {
		cout << element << endl;
	});

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

执行结果 :

90
50
20
70
请按任意键继续. . .
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述


7、代码示例 - 将变换结果输出到标准输出流中


ostream_iterator 函数对象 是 一个模板类 , 其提供了一个输出迭代器 , 可以将元素逐个写入到输出流中 , 通常是 std::ostream 对象 , 如 std::cout 标准输出流 ;

ostream_iterator 函数对象 定义在 <iterator> 头文件中 , 使用前先导入该头文件 ;

// ostream_iterator 输出流迭代器 头文件
#include "iterator"
  • 1
  • 2

ostream_iterator 函数对象 的 构造函数接受两个参数 :

  • 一个输出流对象的引用
  • 一个可选的分隔符字符串 ;

每次迭代器被解引用以写入元素时 , 它都会将元素写入输出流 , 并在元素之间插入分隔符 ;


在下面的代码中 ,

首先 , 创建了一个 vector 数组容器 , 之后该容器 既作为输入容器 , 又作为输出容器 , 将元素输入后 , 计算后 , 在输出 到原来的容器中 ;

	// 创建一个 vector 数组容器
	vector<int> myVector;
  • 1
  • 2

然后 , 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象 ,

// 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象
bind2nd(multiplies<int>(), 10)
  • 1
  • 2

multiplies 函数对象源码如下 : 该函数对象的 重载 函数调用操作符 函数 , 接收 2 个参数 , 使用 bind2nd 函数适配器 为其设置第二个参数为 10 , 那么第一个参数就是 迭代器范围的 元素 ;

	// 向 transform 变换算法中 传入 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象
	// 将变换结果 , 输出到 屏幕 标准输出流 中
	transform(myVector.begin(), myVector.end(), ostream_iterator<int>(cout, " "), bind2nd(multiplies<int>(), 10));
  • 1
  • 2
  • 3

最后 , 将 myVector 数组容器的 元素范围 ( 起始迭代器 和 末尾迭代器 ) 作为输入容器 , 将 myVector 数组容器的 的 起始迭代器 作为输出容器 起始点 , 也就是 将 输入容器 的元素 进行修改 , 再次放回到 该容器中 ;

	// 向 transform 变换算法中 传入 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象
	transform(myVector.begin(), myVector.end(), myVector.begin(), bind2nd(multiplies<int>(), 10));
  • 1
  • 2

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"
// ostream_iterator 输出流迭代器 头文件
#include "iterator"

int main() {

	// 创建一个 vector 集合容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(9);
	myVector.push_back(5);
	myVector.push_back(2);
	myVector.push_back(7);

	// 向 transform 变换算法中 传入 使用 函数适配器 将预定义二元函数对象转成的 一元函数对象
	// 将变换结果 , 输出到 屏幕 标准输出流 中
	transform(myVector.begin(), myVector.end(), ostream_iterator<int>(cout, " "), bind2nd(multiplies<int>(), 10));

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

执行结果 :

90 50 20 70 请按任意键继续. . .
  • 1

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/124019
推荐阅读
  

闽ICP备14008679号