C++言語解説:STL基礎(2)反復子
2003-08-10 |
[C++ Index Top] [Prev] [Next] |
[概要] コンテナの要素へアクセスするために、STLでは反復子を利用します。ここでは反 復子の概要とプログラミング例を学習します。 [構成]・反復子の概要 * 反復子とは * 反復子のタイプ ・vectorコンテナと反復子 * 反復子を使用するメンバ関数 * 反復子の利用例 ●反復子の概要 ◆反復子とは ・反復子(iterator)はコンテナ内の要素を指す汎用的ポインタです。STLにおけるコ ンテナへのアクセスは、この反復子を介して行うのがメインです。反復子はポイン タと同様な演算(++,--,+,-)によって要素へアクセスすることができます。 ・前回レポートの例では、vectorコンテナに対し[]添字演算子でアクセスしましたが 当然vectorコンテナも反復子を持っています。 ・そこで今回は反復子の概要を理解し、反復子を使用したプログラミング例を見るこ とにします。 ◆反復子のタイプ ・反復子には5種類のタイプがあります。 * ランダムアクセス反復子(random access iterator) + 値の設定及び取得の両方に適用できます。 + ランダムアクセスが可能です。 + 演算子は ++,--,+,- を使用できます。 + 添字演算子[]も使用できます。 * 双方向反復子(bidirectional iterator) + 値の設定及び取得の両方に適用できます。 + 前方又は後方に移動できます。 + 演算子は ++,-- が使用できます。 * 前方反復子(forward iterator) + 値の設定及び取得の両方に適用できます。 + 前方にのみ移動できます。 + 演算子は ++ が使用できます。 * 入力反復子(input iterator) + 値の取得に適用できます。 + 前方にのみ移動できます。 + 演算子は ++ が使用できます。 * 出力反復子(output iterator) + 値の取得に適用できます。 + 前方にのみ移動できます。 + 演算子は ++ が使用できます。 ・反復子の種類はコンテナにより異なります。それはコンテナの性質から、最も効率 が良いと思われる反復子が割り当てられていることを意味します。 ●vectorコンテナと反復子 ◆反復子を使用するメンバ関数 ・vectorコンテナで反復子を使用するメンバ関数をリストアップします。 [List1.vectorでiteratorを使用するメンバ関数] ┌────────────────────────────────────┐ * iterator begin(); + vectorの先頭位置を示す反復子を返す * iterator end(); + vectorの末尾を示す反復子を返す * iterator erase(iterator i); + iが示す要素を削除し、次の要素を示す反復子を返す * iterator erase(iterator start, iterator end); + startからendまでの要素を削除し、次の要素を示す反復子を返す * iterator insert(iterator i, const T& val); + iが指す要素の直前にvalを挿入 * void insert(iterator i, int num, const T& val); + iが指す要素の直前にvalをnum個挿入 * template <class InIter> void insert(iterator i, InIter strat, InIter end); + iが示す要素の直前に、startからendの要素を挿入 └────────────────────────────────────┘ ・iteratorの指し示す位置はFig.1のようになります。特にend()の指す位置には注意 が必要です。 ┌────────────────────────────────────┐ vectorコンテナのVectorオブジェクト ┌─┬─┬─┬─┬─┬─ ─┬─┬─┬─┬─┐ │■│●│▲│◆│●│ ・・・ │◆│■│●│▲│ └─┴─┴─┴─┴─┴─ ─┴─┴─┴─┴─┘ ↑ ↑ ↑ ↑ │ i+1 i+3 Vector.end(); │ i++ ※最後の要素ではない i=Vector.begin(); └────────────────────────────────────┘ Fig.1 iteratorの示す位置 ◆反復子の利用例 ・反復子を利用してvectorコンテナにアクセスするプログラム例を示します。 [List2.反復子によるvectorコンテナ要素へのアクセス] ┌────────────────────────────────────┐ // +----+ // | 80 | データファイルを標準入力から読む // | 60 | 合計 : 480 // | 50 | 平均 : 68 // | 70 | データ個数 : 7 // | 60 | データ要素表示 // | 90 | 3番目のデータ(50)前に、全てのデータを挿入 // | 70 | 合計 : 960 // +----+ 平均 : 68 // データ個数 : 14 // データ要素表示 #include <iostream> #include <vector> using namespace std; int Sum(vector<int>& Vector); // 合計 float Average(vector<int>& Vector); // 平均 void Display(vector<int>& Vector); // 要素表示 int main() { vector<int> Vector; //空のvector vector<int>::iterator ip; //vector<int>のiterator int i_data; while(!cin.eof()){ cin >> i_data; Vector.push_back(i_data); } cout << "合計 : " << Sum(Vector) << endl; cout << "平均 : " << Average(Vector) << endl; cout << "データ個数 : " << Vector.size() << endl; Display(Vector); vector<int> Vector2(Vector); //VectorをコピーしたVector2生成 ip = Vector.begin(); // ipはVectorの先頭 ip += 2; // 3番目の要素へ移動 //3番目の手前(2番目)にVecto2全要素を挿入 Vector.insert(ip, Vector2.begin(), Vector2.end()); cout << "合計 : " << Sum(Vector) << endl; cout << "平均 : " << Average(Vector) << endl; cout << "データ個数 : " << Vector.size() << endl; Display(Vector); return 0; } int Sum(vector<int>& Vector) { // 合計 int sum_ret = 0; vector<int>::iterator ip = Vector.begin(); while(ip != Vector.end()) { sum_ret += *ip; ip++; } return sum_ret; } float Average(vector<int>& Vector) { // 平均 int sum = 0; float average_ret; vector<int>::iterator ip = Vector.begin(); while(ip != Vector.end()) { sum += *ip; ip++; } average_ret = sum/Vector.size(); return average_ret; } void Display(vector<int>& Vector) { // 要素表示 vector<int>::iterator ip = Vector.begin(); while(ip != Vector.end()) { cout << " " << *ip; ip++; } cout << endl; return; } └────────────────────────────────────┘ ┌────────────────────────────────────┐ [出力結果] 合計 : 480 平均 : 68 データ個数 : 7 80 60 50 70 60 90 70 合計 : 960 平均 : 68 データ個数 : 14 80 60 80 60 50 70 60 90 70 50 70 60 90 70 └────────────────────────────────────┘ ・main()関数及びローカル関数で定義される反復子ipは、vector<int>テンプレート で使用されるiteratorとして定義されます。 vector<int>::iterator ip ・vectorコンテナ内の要素を見るwhileループでは、Vector.end()と同じになるまで 反復子ipをインクリメントしています。 ・要素の値については、今回は単純なint型のvectorなので、*ipが値そのものを指し ます。int型ではなくクラスや構造体の場合、然るべきメンバを経由して目的の値 を取得します。 ・Vector2オブジェクト生成時にはVectorを引数としています。この場合Vector2の要 素にVectorの要素がコピーされます。同一タイプのオブジェクトを引数にするコン ストラクタがvectorには定義されていることを意味しています。 ・main関数の中ほどで、反復子ipに2を加えています。これにより、ipの指す要素は 2個分前進します。 ・その後insert()メンバ関数で、ip(3番目)の手前に、Vector2の最初から最後までを 入れています。この場合もvector2.end()を挿入終了位置に指定している点は注意 下さい。 ・この例で反復子の概要は把握できたと思います。次回はアルゴリズムを適用してみ たいと思います。 [Revision Table] |Revision |Date |Comments |----------|-----------|----------------------------------------------------- |1.00 |2003-08-10 |初版 |1.01 |2003-08-18 |リンク追加 [end] |
Copyright(C) 2003 Altmo
|
[C++ Index Top] [Prev] [Next] |