C++ 输出迭代器
什么是输出迭代器
输出迭代器是C++ STL迭代器层次结构中的基本类型之一,专门用于向容器或目的地写入数据。它是一种单向、单次遍历的迭代器,只支持向前移动且每个位置只能写入一次。
输出迭代器是STL迭代器中要求最少的一类迭代器,主要关注写入操作而非读取操作。
输出迭代器的特性
输出迭代器具有以下主要特性:
- 写入功能:通过赋值操作将值写入指向的位置
- 前置和后置递增:可以通过
++iter
和iter++
向前移动 - 单向前进:只能向前移动,不能后退
- 单次遍历:每个位置只应写入一次
- 无比较操作:输出迭代器不支持比较操作(如
==
或!=
)
输出迭代器的操作
输出迭代器支持的基本操作包括:
操作 | 描述 |
---|---|
*it = value | 向迭代器指向的位置写入值 |
++it | 前置递增,移至下一位置 |
it++ | 后置递增,移至下一位置 |
it = it2 | 赋值操作 |
标准库中的输出迭代器
C++标准库中提供了几种常见的输出迭代器:
1. std::ostream_iterator
这是一个用于向输出流写入数据的迭代器适配器。
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
// 创建一个输出流迭代器,向std::cout写入数据,每个元素后加空格
std::ostream_iterator<int> output_iter(std::cout, " ");
// 使用copy算法将vector中的元素复制到输出流
std::copy(nums.begin(), nums.end(), output_iter);
return 0;
}
输出:
1 2 3 4 5
2. std::back_insert_iterator
用于在容器末尾插入元素的输出迭代器。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination;
// 创建一个back_insert_iterator
std::back_insert_iterator<std::vector<int>> back_it(destination);
// 复制元素到destination
std::copy(source.begin(), source.end(), back_it);
// 输出destination的内容
for(int num : destination) {
std::cout << num << " ";
}
return 0;
}
输出:
1 2 3 4 5
3. std::front_insert_iterator
用于在容器前端插入元素的输出迭代器。
#include <iostream>
#include <deque>
#include <iterator>
#include <algorithm>
int main() {
std::deque<int> source = {1, 2, 3, 4, 5};
std::deque<int> destination;
// 创建一个front_insert_iterator
std::front_insert_iterator<std::deque<int>> front_it(destination);
// 复制元素到destination
std::copy(source.begin(), source.end(), front_it);
// 输出destination的内容
for(int num : destination) {
std::cout << num << " ";
}
return 0;
}
输出:
5 4 3 2 1
4. std::insert_iterator
用于在容器指定位置插入元素的输出迭代器。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination = {10, 20, 30, 40, 50};
// 创建一个insert_iterator,插入点为destination的第三个元素位置
std::insert_iterator<std::vector<int>> insert_it(destination, destination.begin() + 2);
// 复制元素到destination
std::copy(source.begin(), source.end(), insert_it);
// 输出destination的内容
for(int num : destination) {
std::cout << num << " ";
}
return 0;
}
输出:
10 20 1 2 3 4 5 30 40 50
便捷函数
STL提供了一些便捷函数来创建插入迭代器,而不需要明确指定迭代器类型:
std::back_inserter(container)
- 创建back_insert_iterator
std::front_inserter(container)
- 创建front_insert_iterator
std::inserter(container, iterator)
- 创建insert_iterator
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination;
// 使用back_inserter便捷函数
std::copy(source.begin(), source.end(), std::back_inserter(destination));
// 输出destination的内容
for(int num : destination) {
std::cout << num << " ";
}
return 0;
}
输出:
1 2 3 4 5
实际应用场景
文件处理
使用输出迭代器将数据写入文件:
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> data = {10, 20, 30, 40, 50};
// 打开文件用于写入
std::ofstream outFile("output.txt");
if (!outFile) {
std::cerr << "无法打开文件!" << std::endl;
return 1;
}
// 创建输出文件流迭代器
std::ostream_iterator<int> file_it(outFile, "\n");
// 将数据写入文件
std::copy(data.begin(), data.end(), file_it);
std::cout << "数据已成功写入文件" << std::endl;
return 0;
}
数据转换和过滤
使用输出迭代器结合算法进行数据转换:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::vector<int> even_numbers;
// 过滤出偶数并存入新容器
std::copy_if(numbers.begin(), numbers.end(),
std::back_inserter(even_numbers),
[](int n) { return n % 2 == 0; });
std::cout << "偶数: ";
for(int num : even_numbers) {
std::cout << num << " ";
}
std::vector<int> squared_numbers;
// 计算平方并存入新容器
std::transform(numbers.begin(), numbers.end(),
std::back_inserter(squared_numbers),
[](int n) { return n * n; });
std::cout << "\n平方数: ";
for(int num : squared_numbers) {
std::cout << num << " ";
}
return 0;
}
输出:
偶数: 2 4 6 8 10
平方数: 1 4 9 16 25 36 49 64 81 100
合并数据流
使用输出迭代器合并多个数据源:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> first_half = {1, 2, 3, 4, 5};
std::vector<int> second_half = {6, 7, 8, 9, 10};
std::vector<int> merged;
// 保留merged的容量以提高性能
merged.reserve(first_half.size() + second_half.size());
// 将第一个容器的内容复制到merged
std::copy(first_half.begin(), first_half.end(), std::back_inserter(merged));
// 将第二个容器的内容追加到merged
std::copy(second_half.begin(), second_half.end(), std::back_inserter(merged));
std::cout << "合并后的数据: ";
for(int num : merged) {
std::cout << num << " ";
}
return 0;
}
输出:
合并后的数据: 1 2 3 4 5 6 7 8 9 10
自定义输出迭代器
我们可以创建自己的输出迭代器来满足特殊需求。以下是一个简单的示例,创建一个用于特殊格式化输出的迭代器:
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
// 自定义输出迭代器
class FormattedOutputIterator {
private:
std::ostream& out;
std::string prefix;
std::string suffix;
bool is_first;
public:
// 迭代器特性
using iterator_category = std::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
// 构造函数
FormattedOutputIterator(std::ostream& os, const std::string& pre, const std::string& suf)
: out(os), prefix(pre), suffix(suf), is_first(true) {}
// 赋值操作符
template<typename T>
FormattedOutputIterator& operator=(const T& value) {
if (is_first) {
is_first = false;
} else {
out << suffix;
}
out << prefix << value;
return *this;
}
// 解引用操作符(返回自身)
FormattedOutputIterator& operator*() { return *this; }
// 前置递增操作符
FormattedOutputIterator& operator++() { return *this; }
// 后置递增操作符
FormattedOutputIterator operator++(int) { return *this; }
};
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用自定义迭代器,每个数字前添加"Item: ",后加", "
FormattedOutputIterator formatter(std::cout, "Item: ", ", ");
std::copy(numbers.begin(), numbers.end(), formatter);
std::cout << "End of list";
return 0;
}
输出:
Item: 1, Item: 2, Item: 3, Item: 4, Item: 5End of list
总结
输出迭代器是C++ STL迭代器体系中的一类基础迭代器,专门用于写入操作。它们具有以下特点:
- 专注于写入操作而非读取操作
- 只能向前移动(不能倒退)
- 每个位置只能写入一次
- 不支持比较操作
标准库提供了多种常见的输出迭代器,包括:
std::ostream_iterator
- 向输出流写入数据std::back_insert_iterator
- 在容器末尾插入元素std::front_insert_iterator
- 在容器前端插入元素std::insert_iterator
- 在容器指定位置插入元素
输出迭代器在文件处理、数据转换、数据过滤和合并等多种场景中有广泛应用。理解和熟练使用输出迭代器是掌握STL的重要一步。
练习
-
创建一个程序,使用
std::ostream_iterator
将一个vector
中的所有元素以JSON数组格式输出(如[1,2,3,4,5]
)。 -
编写一个程序,从用户输入读取一系列整数,然后使用不同类型的插入迭代器将它们添加到不同的容器中。
-
使用
std::transform
和输出迭代器将一个字符串向量中的所有字符串转换为大写,并存储在新的向量中。 -
创建一个自定义输出迭代器,它将每个写入的数据项编号并格式化输出,例如"1. 苹果","2. 香蕉"等。
-
使用输出迭代器实现一个简单的CSV文件生成器,将多个数据容器的内容写入CSV格式文件。
额外资源
- C++参考文档 - 迭代器库
- Effective STL (Scott Meyers) - 包含关于迭代器高效使用的建议
- C++ Primer (第5版) - 详细介绍了迭代器的概念和用法
记住,虽然输出迭代器功能有限,但正是这种简化的接口使它们能够在各种不同的场景中灵活使用,特别是结合STL算法时。