ページ 11

イテレータについて

Posted: 2012年7月27日(金) 14:48
by peach
STLのvector型について勉強しているのですが、いまいちイテレータの使い方がわかりません。

コード:

#include<iostream>
#include<vector>

using namespace std;

struct Point
{
     int x;
     int y;
};

int main()
{
     vector<vector<Point>> point;
     vector<vector<Point>>::iterator it;
     vector<vector<Point>>::const_iterator& end = point.end();

     //ここでpointに不定のデータが入る

     for(it = point.begin() ;it == end;++it )
     {
          //ここでイテレータを使ってpointからデータを選別
     }
     
     return 0;
}

というようなことがしたいのですがどういう風にすればいいですか?
選別の部分は、連続量の両端のみを取得して、他は切り捨てると言う風にする予定でこっちは大丈夫です。

Re: イテレータについて

Posted: 2012年7月27日(金) 14:54
by nil
vectorなら[]演算子の添字によるアクセスでいいのでは?
あと
it != endです

Re: イテレータについて

Posted: 2012年7月27日(金) 14:55
by beatle
it == end
では、pointに要素が1つも無い場合にのみfor文が実行されてしまいますよ。
典型的な書き方は次のようになります

コード:

vector<vector<Point> > point;
vector<vector<Point> >::iterator it;
for (it = point.begin(); it != point.end(); ++it)
{
}
イテレータit自体は普通のポインタと同じように扱えばいいです。
すなわち、itは vector<Point>* と同じような型だと思ってください(実のところ、本当にこの型の場合もあります)。

ですから it を使って何かするには次のようにすればいいでしょう。

コード:

it->size(); // itが指すPoint配列の要素数を取得

Point p;
p.x = 10; p.y = 20;
it->at(0) = p; // itが指すPoint配列の先頭に p をコピー
(*it).at(0) = 0; // こんな書き方も
(*it)[0] = 0; // こんな書き方もあります。

Re: イテレータについて

Posted: 2012年7月28日(土) 01:20
by へにっくす

コード:

#include "stdafx.h"

#include <iostream>
#include <vector>

using namespace std;

struct Point
{
	int x;
	int y;
};

int main()
{
	vector<vector<Point>> point;
	vector<vector<Point>>::iterator it;

	//ここでpointに不定のデータが入る

	for(it = point.begin(); it != point.end(); it++ )
	{
		vector<Point> p = *it;
		vector<Point>::iterator pit;
		for ( pit = p.begin(); pit != p.end(); pit++ )
		{
			printf("(%d,%d)\n", pit->x, pit->y);
		}
	}

	return 0;
}
私は上のような書き方になるね。
わざわざendなんて用意しなくても、これで十分分かる。
ところで以下の書き方は、昔のコンパイラではエラーになったんだけど、いまVS2005でコンパイルしたら通りゃがったさコイツ 笑

コード:

vector<vector<Point>> point;
昔は演算子'>>'と混同するってんで

コード:

vector<vector<Point> > point;
スペースをはさむ必要があったんだけどなあ…進化したな

Re: イテレータについて

Posted: 2012年7月28日(土) 14:06
by beatle
へにっくすさんのやり方だと23行目で配列のコピーが発生するために効率が悪いと思います。効率を無視すれば問題ない書き方です。
itのままだと扱いにくい、でも配列のコピーが発生するのも嫌だなあ、ってときは

コード:

vector<Point>& p = *it;
などと、参照にするのがいいでしょう。

>>の間にスペースを挟まなくていいのは、実は C++11 の規格です。おそらく VS 2005 は独自に拡張して対応しているのでしょう。

Re: イテレータについて

Posted: 2012年7月28日(土) 14:52
by peach
回答ありがとうございます。
涼雅さん、[]によるアクセスですが、[]だと確保していない領域にもアクセスできてしまうのでイテレータを使ってアクセスしようと思いました。

beatleさん、it == endじゃなくてit != endですね。アクセスする方法も分かったのでこれで大丈夫そうです。

へニックスさん、VS2010は微妙にC++11に対応していて、C++11では<>が山括弧として正式に導入されているためにスペースがいらないという仕様です。また、endを使っている理由ですが、endも別で使う予定にあるのでいいかなとは思ってたのですが、どうなんですかね?

コード:

  for(it = point.begin(); it != point.end(); it++ )
    {
        vector<Point> p = *it;
        vector<Point>::iterator pit;
        for ( pit = p.begin(); pit != p.end(); pit++ )
        {
            printf("(%d,%d)\n", pit->x, pit->y);
        }
    }
因みにこの書き方でやると2次元配列の各行毎にアクセスできるのですか?

Re: イテレータについて

Posted: 2012年7月28日(土) 17:56
by peach
すいません自己解決しました。
よくよく考えたら2次配列の中にアクセスできますね。
ありがとうございました

Re: イテレータについて

Posted: 2012年7月28日(土) 17:56
by peach
すいません自己解決しました。
よくよく考えたら2次配列の中にアクセスできますね。
ありがとうございました

Re: イテレータについて

Posted: 2012年7月28日(土) 19:08
by かずま
peach さんが書きました:すいません自己解決しました。
よくよく考えたら2次配列の中にアクセスできますね。

「2次配列の中にアクセスできます」の意味が分かりません。
イテレータを使わなくて済んだということでしょうか?

この掲示板では、解決したら、実際にどのように解決したかを質問者が書くことになっています。

また、回答者の皆さんは最初の質問の
「//ここでイテレータを使ってpointからデータを選別」にしか回答していません。
「//ここでpointに不定のデータが入る」についてはどのように自己解決されたのでしょうか?

例えば、

コード:

3 4
1 2  3 4  5 6  7 8
9 10  11 12  13 14  15 16
17 18  19 20  21 22  23 24
のような入力データ(最初の2つはサイズ、残りはデータ)を読み込んで、
次のような表示を行うプログラムを見せてください。

コード:

 (1,2) (3,4) (5,6) (7,8)
 (9,10) (11,12) (13,14) (15,16)
 (17,18) (19,20) (21,22) (23,24)

Re: イテレータについて

Posted: 2012年7月28日(土) 20:38
by peach
そうだったんですか。

まず不定のデータが入るという部分ですがここはカメラからの入力を受けて変換していき境界部を座標として抽出しているためにランダムなデータという表現にしました。

2次元配列にアクセスできると言うのは、ちょっと表現がわるかったですね。
上の内容につながるのですが、別にもう一つ呼び出さないといけない関数があってそれを呼びだせば直接vectorを触る必要がなかったというわけです。