構造体のベクターの一部の要素のマージについて – プログラミング – Home

構造体のベクターの一部の要素のマージに...
 
通知
すべてクリア

[解決済] 構造体のベクターの一部の要素のマージについて


ソイレントグリーン
 ソイレントグリーン
(@ソイレントグリーン)
ゲスト
結合: 17年前
投稿: 65
Topic starter  

いつもお世話になります、vector型で構造体データを持ち、その構造体の中のint型のデ
ータだけをマージをしたいのですが、下記のように書きましたら、このようなエラーが出
てしまうのですが、何処がおかしいのでしょうか?
ご教示お願い出来ませんでしょうか。

error C2100: 間接指定演算子 (*) の使い方が正しくありません。
コンパイルされたクラスの テンプレート のインスタンス化 '_OutIt
std::_Merge<int,int,_OutIt,std::_Iter_random_helper3<_Cat1,_Cat2,_Cat3>::_Iter_r
andom_cat>
(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt,_InOutItCat,std::_Range_checked_iterator_tag
)' の参照を確認してください
with
[
_OutIt=std::_Vector_iterator<int,std::allocator<int>>,
_Cat1=std::_Int_iterator_tag,
_Cat2=std::_Int_iterator_tag,

_Cat3=std::_Vector_iterator<int,std::allocator<int>>::iterator_category,
_InIt1=int,
_InIt2=int,

_InOutItCat=std::_Iter_random_helper3<std::_Int_iterator_tag,std::_Int_iterator_
tag,std::_Vector_iterator<int,std::allocator<int>>::iterator_category>::_Iter_ra
ndom_cat
]
コンパイルされたクラスの テンプレート のインスタンス
化 'std::_Vector_iterator<_Ty,_Alloc>
std::merge<int,int,std::_Vector_iterator<_Ty,_Alloc>>
(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt)' の参照を確認してください
with
[
_Ty=int,
_Alloc=std::allocator<int>,
_InIt1=int,
_InIt2=int,
_OutIt=std::_Vector_iterator<int,std::allocator<int>>
]
error C2100: 間接指定演算子 (*) の使い方が正しくありません。
error C2100: 間接指定演算子 (*) の使い方が正しくありません。
error C2100: 間接指定演算子 (*) の使い方が正しくありません。
// VS2005 VC
#include <algorithm>
#include <string>
#include <vector>

struct data {
data(int d) : yymmdd(d) {}
int yymmdd;
std::string code;
double openprice;
};

int main() {
std::vector<data> v;
v.push_back( data(1) );
v.push_back( data(2) );
v.push_back( data(3) );
std::vector<data> v2;
v2.push_back( data(4) );
v2.push_back( data(5) );
v2.push_back( data(6) );
std::vector<int> dist;
std::vector<data>::iterator iter = v.begin();
std::vector<data>::iterator iter2 = v2.begin();
std::vector<int>::iterator distiter = dist.begin();

std::vector<data>::iterator enditer = v.end();
std::vector<data>::iterator enditer2 = v2.end();

std::merge( iter->yymmdd, enditer->yymmdd, iter2->yymmdd, enditer2->yymmdd,
distiter);
}


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

intのマージってどんな結果を期待していますか?
std::mergeはソート済みの二つのコンテナを一つのマージ済みコンテナにしちゃうんで
すけど。


返信引用
ソイレントグリーン
 ソイレントグリーン
(@ソイレントグリーン)
ゲスト
結合: 17年前
投稿: 65
Topic starter  

επιστημηさん、お世話になります
>>intのマージってどんな結果を期待していますか?
私また勘違いしてますでしょうか?
今回の場合ですと、
std::vector<int> distコンテナに
1, 2, 3, 4, 5, 6を代入したいのですが


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

#include <algorithm>
#include <string>
#include <vector>
#include <iterator>
#include <iostream>

struct data {
data(int d) : yymmdd(d) {}
int yymmdd;
std::string code;
double openprice;
};

inline
bool operator<(const data& x, const data& y) {
return x.yymmdd < y.yymmdd;
}

inline int pick_yymmdd(const data& x) {
return x.yymmdd;
}

int main() {
std::vector<data> v;
v.push_back( data(1) );
v.push_back( data(3) );
v.push_back( data(5) );

std::vector<data> v2;
v2.push_back( data(2) );
v2.push_back( data(4) );
v2.push_back( data(6) );

// vとv2をマージしてtempに
std::vector<data> temp;
std::merge(v.begin(), v.end(), v2.begin(), v2.end(), std::back_inserter
(temp));

// tempからyymmddだけをとりだしてdistに
std::vector<int> dist;
std::transform(temp.begin(), temp.end(), std::back_inserter(dist),
&pick_yymmdd);
// 確認
for ( int i = 0; i < dist.size(); ++i ) {
std::cout << dist[i] << std::endl;
}
}


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

>>intのマージってどんな結果を期待していますか?
> 私また勘違いしてますでしょうか?

きっと 思いっきり勘違い してます。


返信引用
ソイレントグリーン
 ソイレントグリーン
(@ソイレントグリーン)
ゲスト
結合: 17年前
投稿: 65
Topic starter  

お世話になります、
飲み込めなくてすみません、三点ほど質問させてもらってもいいでしょうか

※1
inline bool operator<(const data& x, const data& y) {
return x.yymmdd < y.yymmdd;
}
ここでの>(比較演算子)のオーバーロードなのですが、何処で作用してますでしょう
か?

※2
merge関数の最期の引数ですが、επιστημηさんは
std::back_inserter (temp)を末尾挿入イテレータとして使われていると
思うのですが、格納方向を考えずに、イテレータtemp.begin()としますと
Assertionで落ちてしまうのですがこの使い方は間違いなのですね?

※3
先に私が書きましたiter->yymmddこの書き方はイテレータにはなってないという解釈で宜
しいでしょうか?


返信引用
RAPT
 RAPT
(@RAPT)
ゲスト
結合: 22年前
投稿: 310
 

> ※1
std::merge(v.begin(), v.end(), v2.begin(), v2.end(), std::back_inserter(temp));
でマージを行うときの比較演算子として。

> ※2
vector は末尾にしか追加できないから。

> ※3
YES. ただの値参照です。


返信引用
ソイレントグリーン
 ソイレントグリーン
(@ソイレントグリーン)
ゲスト
結合: 17年前
投稿: 65
Topic starter  

RAPTさんの世話になります
※2、※3はよく分かりましたが
※1がmerge関数の処に比較演算子を書かなくても、作用するんですね、知りませんでし
た、merge関数で、比較関数を使う場合、私はこの様に書くものと思い込んでいました。
C++っぽくないですが^^;

inline bool compare(const data& x, const data& y) {
return x.yymmdd < y.yymmdd;
}

std::merge(v.begin(), v.end(), v2.begin(), v2.end(), std::back_inserter (temp),
&::compare);


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

> ※1 merge関数の処に比較演算子を書かなくても、作用するんですね

てゆーか、mergeに比較オブジェクトを書かないとき、operator < が適用される。
# ので、ちゃんと定義したらなあかん。

> ※2 std::back_inserter (temp)を末尾挿入イテレータとして使われていると
> 思うのですが、格納方向を考えずに、イテレータtemp.begin()としますと
> Assertionで落ちてしまうのですがこの使い方は間違いなのですね?

temp.size()がマージされる要素数より大きければ問題なし。
このサンプルでは temp.size()==0 なのでふっとぶ。

> ※3 iter->yymmddこの書き方はイテレータにはなってないという解釈で宜
しいでしょうか?

どうひいき目に見たところでイテレータじゃないわねぇ。
# おまけに end()->yymmdd はふっとぶし。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

> C++っぽくないですが^^;

なぜに?


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

<algorithm> や <utility> は原理的にそんなに難しいことしてないので
# <iterator> とかのほうが難しい
ソース嫁といっておこう。

merge については (前提条件の表明等を除けば) これだけ。
oit merge(iit b1, iit e1, iit b2, iit e2, oit r) {
 while (b1!=e1 && b2!=e2) { // 元コンテナのどちらかが尽きるまで
  if (*b2<*b1) *r=*b2, ++b2; // 小さいほうをコピー
  else *r=*b1, ++b1;
  ++r;
 }
 // 片側コンテナが尽きているはずなので、残っているほうをコピー
 return copy(b2,e2, copy(b1,e1, r));
}
*b2<*b1 の判定の際に operator< (const T, const T) が暗黙に使われる

述語バージョンは *b2<*b1 が pred(*b2, *b1) に変わるだけ

C++ っぽいというのはこーいう話なのかな?
merge(v1.begin(), v1.end(), v2.begin(), v2.end(),
   std::back_inserter(r), std::less<data>());
これは述語として less<data> を指定しているわけだけど、結局のところ
less<T> は operator<(const data&, const data&) を使うことを述語として
明示しているだけであって operator < を実装する必要があることは同じ。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

...あ、yymmddを抽出してからmergeしたほが簡単だわ♪

#include <algorithm>
#include <string>
#include <vector>
#include <iterator>
#include <iostream>

struct data {
data(int d) : yymmdd(d) {}
int yymmdd;
std::string code;
double openprice;
};

inline int pick_yymmdd(const data& x) {
return x.yymmdd;
}

int main() {
std::vector<data> v;
v.push_back( data(1) );
v.push_back( data(3) );
v.push_back( data(5) );

std::vector<data> v2;
v2.push_back( data(2) );
v2.push_back( data(4) );
v2.push_back( data(6) );

std::vector<int> dist;
std::transform(v.begin(), v.end(), std::back_inserter(dist), &pick_yymmdd);
std::transform(v2.begin(), v2.end(), std::back_inserter(dist), &pick_yymmdd);
std::inplace_merge(dist.begin(), dist.begin()+v.size(), dist.end());
// 確認
for ( int i = 0; i < dist.size(); ++i ) {
std::cout << dist[i] << std::endl;
}
}


返信引用
ソイレントグリーン
 ソイレントグリーン
(@ソイレントグリーン)
ゲスト
結合: 17年前
投稿: 65
Topic starter  

お世話になります。
επιστημηさん
>なぜに?
なんとなくオーバーロードした多重演算子を使うと、いかにもC++っぽく思える
という、単なる個人的な主観です、オーバーロードの使い時というか、使うに相応しい
場面がよく、判っていない人なので、こういう時に使うのだなぁーと、すごく勉強にな
りました。
tetrapodさん
>ソース嫁といっておこう。
まったくですね、ただこの度、merge関数もですが、vector型のデータで
構造体のElementの更にその中のint型のオブジェクトに対するアクセス方法が、
ポカーンだったので、正直迷ったのですが、transform関数と比較演算子の合わせ業を御
教示して頂、原理もよく分かり、私にとって多きな収穫でした。
いつもとぼけた質問ばかりして申し訳ございませんが、大変ありがたく感じておりま
す。解決とさせて頂きます。
処でC++を深く学ぶ上で、Bjarne Stroustrup氏の『プログラミング言語C++第3版』とい
う本ですが、Amazonの書評とかを読みますと、難解な本で且つ、誤訳も多いという印象
を受けたのですが、皆さんのご意見はいかがなものでしょうか、ざっくりとで善いです
ので雑感、所感等を教えて頂けませんでしょうかお願いします。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

> Bjarne Stroustrup氏の『プログラミング言語C++第3版』という本ですが、
> Amazonの書評とかを読みますと、難解な本で且つ、誤訳も多いという印象を
> 受けたのですが、皆さんのご意見はいかがなものでしょうか

書評の通り。誤訳については正誤表が出てるみたい。
難解なのは気にしない。初心者向けを狙ってるわけじゃないだろうから。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました