C++STL之迭代器

迭代器除了在STL中遍历序列对象外,还有其他更多的迭代器被iterator所定义。iterator头文件定义迭代器的几个模板将数据从源传到目的地。流迭代器(stream iterator)作为指向输入或输出流的指针,它们可以用来在流和任何使用迭代器的源或目的地之间传输数据,如算法。插入迭代器(inserter iterator)可以将数据传输给一个基本的序列容器。Iterator头文件定义了两个流迭代器模板,其中istream_iterator<T>用于输入流,ostream_iterator<T>用于输出流,T是要从流中提取的或者写入流中的对象类型。头文件还定义了三个插入模板:inserter<T>、back_inserter<T>和front_inserter<T>,其中T是在其中插入数据的序列容器的类型。

输入流迭代器

创建输入流迭代器:

istream_iterator<int> input(cin);

此代码创建了一个istream_iterator<int>类型的迭代器 input,可以指向流中int类型的对象。这个构造函数的实指定与迭代器相关的实际流,因此它是一个可以从标准输入流cin中读取整数的迭代器。默认的istream_iterator<T>构造函数创建一个end-of-stream迭代器。它等价于通过调用容器的end()函数获得容器的end迭代器。下面代码说明了如何创建cin的end-of-stream迭代器来补充input迭代器:

istream_iterator<int> inputEnd;

现在有了一对迭代器,定义cin中一个int类型的值的序列,可以用这些迭代器将cin中的值加载到vector<int>中。

vector<int> numbers;
cout<<”input numbers , end by zero”<<endl;
istream_iterator<int> input(cin),inputEnd;
while(input != inputEnd)
{
    numbers.push_back(*input++);
}

可以看出,只要不是cin的end-of-stream,就会继续执行while输入数据,那么怎样才会产生end-of-stream的条件了,可以输入Ctrl+Z或输入一个无效的字符(如字母),就会产生end-of-stream条件。

当然,不只限于只能使用输入流迭代器作为循环的控制变量。它们可以向算法传递数据,如numeric头文件中的accumulate()。

cout<<”input numbers separated by spaces and a letter to end”<<endl;
istream_iterator<int> input(cin),inputEnd;
cout<<”the sum of you inputed numbers is<<accumulate(input,inputEnd,0)<<endl;

sstream头文件定义basic_istringstream<T>类型,这个类型定义可以访问流缓冲区中的数据的对象类型,如string对象。这个头文件还将类型istringstream定义为basic_istringstream<char>,它将是char类型的字符流。可以从string对象中构造一个istringstream对象,这意味着从string对象中读取数据,就像从cin中读取数据一样。因为istringstream对象是一个流,所以可将它传递给一个输入迭代器构造函数,并用该迭代器访问底层流缓冲区中的数据。如:

string data[] = {“1.2 12.6 3.6 98 5.3 7.1”};
Istringstream input(data);
Istream_iterator<double> begin(input),end;
cout<<”the sum of you inputed numbers is<<accumulate(begin,end,0.0)<<endl;

由于从string对象data中创建istringstream对象,因此可以像流一样从data中读取数据。此处accumulate()的第三个参数应为0.0,因为第三个参数确定结果的类型,此处保证返回double类型的值。

实例:

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <iterator>
using std::cout;
using std::cin;
using std::endl;
using std::string;

int main() 
{
    std::map<string, int> words;           // Map to store words and word counts
    cout << "Enter some text and press Enter followed by Ctrl+Z then Enter to end:"
        << endl << endl;

    std::istream_iterator<string> begin(cin); // Stream iterator 
    std::istream_iterator<string> end;        // End stream iterator

    while(begin != end )                      // Iterate over words in the stream 
        words[*begin++]++;                      // Increment and store a word count

    // Output the words and their counts
    cout << endl << "Here are the word counts for the text you entered:" << endl;
    for(auto iter = words.begin() ; iter != words.end() ; ++iter) 
        cout << std::setw(5) << iter->second << " " << iter->first << endl;

    return 0;
}

插入迭代器

插入迭代器(inserter iterator)是一个可以访问序列容器vector<T>、deque<T>和list<T>添加新元素的迭代器。有3个创建插入迭代器的模板:

Back_insert_iterator<T>在类型T的容器末尾插入元素。容器必须提供push_back()函数。

Front_insert_iterator<T>在类型T的容器开头插入元素。同样push_front()对容易可用。

Insert_iterator<T>在类型T的容器内从指定位置开始插入元素。这要求容器有一个insert()函数,此函数接受两个参数,迭代器作为第一个实参,要插入的项作为第二个实参。

前两个插入迭代器类型的构造函数接受一个指定要在其中插入元素的容器的实参。如:

list<int> numbers;
front_insert_iterator<list<int> > iter(numbers);

向容器中插入值:

*iter = 99;

也可以将front_inserter()函数用于numbers容器:

front_inserter(numbers) = 99;

这几行代码为numbers列表创建了一个前段插入器,并用它在开头插入99。front_inserter()函数的实参是运用迭代器的容器。

 

insert_iterator<T>迭代器的构造函数需要两个实参:

insert_iterator<vector<int> > iter(numbers,numbers.begin());

该构造函数的第二个实参是一个指定在何处插入数据的迭代器。向此容器赋值:

for (int i = 0; i < 100; i++)
    *iter = i + 1;

代码执行后,前100个元素的值依次为100,99,…,1。

 

输出流迭代器

为了补充输入流迭代器模板,ostream_iterator<T>模板提供了向输出流写类型T的对象的输出流迭代器。

ostream_iterator<int> out(cout);

该模板的实参int指定要处理的数据类型,构造函数实参cout指定将作为数据的目的地的流,以便cout迭代器能将int类型的值写到标准输出流中。如:

int data [] = {1,2,3,4,5,6,7,8,9};
vector<int> numbers(data,data+9);
copy(numbers.begin(),numbers.end(),out);

在algorithm头文件中定义的copy()算法将由前两个迭代器实参指定的对象序列复制到第三个实参指定的输出迭代器。此代码执行结果为:123456789.

但现在写到标准输出流中的值没有空格。第二个输出流迭代器构造函数能解决这一点:

ostream_iterator<int> out(cout,” ”);

现在将输出1 2 3 4 5 6 7 8 9

实例:

#include <iostream>
#include <numeric>
#include <vector>
#include <iterator>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
using std::istream_iterator;
using std::ostream_iterator;
using std::back_inserter;
using std::accumulate;


int main()
{
    vector<int> numbers;
    cout << "Enter a series of integers separated by spaces" 
        << " followed by Ctrl+Z or a letter:" << endl;

    istream_iterator<int> input(cin), input_end;
    ostream_iterator<int> out(cout, " ");

    copy(input, input_end, back_inserter<vector<int>>(numbers));

    cout << "You entered the following values:" << endl;
    copy(numbers.begin(), numbers.end(), out);

    cout << endl << "The sum of these values is " 
        << accumulate(numbers.begin(), numbers.end(), 0) << endl;

    return 0;
}

 

posted @ 2012-08-28 19:31  Loylin  阅读(13208)  评论(0编辑  收藏  举报