迭代器除了在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; }