vectorコンテナでmapのpairのようなことがしたいのですが

[戻る]
とほほ 2008/02/22(金) 10:29:27
宜しくお願いいたします。
行いたいことはvectorコンテナでmapのpairのような振舞いさせたくて
下記のような実装を行い目的は果たせているのですが、もっとエレガントに
描けないでしょうか、ご教示お願いいたします。
find_if()を使ったらできそうなのですが力が無くてできません(´〜`;)トホホ・・
環境:WinXP/VS2005 Express

/*
構造体の特定の要素を比較し、等しければ同じ位置にある他の要素を取得する
*/
#include <iostream>
#include <vector>
#include <string>

using namespace std;

struct tagStructure {
  int count;
  string yymmdd;
  tagStructure( int n = 0, string str = "" ) : count( n ), yymmdd( str ){}
};

int main()
{
  char buff[32];
  string str;
  vector<tagStructure> vec;
  tagStructure tagst;
  for(unsigned int i = 0; i < 4; ++i) {
    tagst.count = i;
    _itoa_s( static_cast<unsigned int>( i ), buff, sizeof( buff ), 10 );
    str = buff;
    tagst.yymmdd = str + "日経過";
    vec.push_back(tagst);
  }

  for( unsigned int i = 0; i < vec.size(); ++i )
    cout << vec[ i ].count << " , " << vec[ i ].yymmdd << endl;

  static const int magicNum = 3;

  vector<tagStructure>::iterator it = vec.begin();
  while ( it < vec.end() ) {
    if( magicNum == it->count )
      cout << it->yymmdd << endl;
    ++it;
  }
  
  return 0;
}

επιστημη [HomePage] 2008/02/22(金) 10:59:22
#include <iostream>   // cout
#include <string>     // string
#include <vector>     // vector
#include <utility>    // pair
#include <algorithm>  // remove_copy_if
#include <functional> // bind1st
#include <iterator>   // ostream_iterator

using namespace std;

struct Structure : public pair<int,string> {
  Structure(int n) : pair<int,string>(n,"") {}
  Structure(int n, const string& s) : pair<int,string>(n,s) {}
};

struct neq : binary_function<Structure,Structure,bool> {
  bool operator()(const Structure& x, const Structure& y) const {
    return x.first != y.first;
  }
};

ostream& operator<<(ostream& stream, const Structure& x) {
  return stream << x.first << ':' << x.second;
}

int main() {
  vector<Structure> vec;
  vec.push_back(Structure(1,"one"));
  vec.push_back(Structure(2,"two"));
  vec.push_back(Structure(1,"eins"));
  vec.push_back(Structure(3,"three"));
  vec.push_back(Structure(1,"いち"));
  vec.push_back(Structure(1,"壱"));
  remove_copy_if(vec.begin(), vec.end(), 
                 ostream_iterator<Structure>(cout,"\n"),
                 bind1st(neq(),Structure(1)));
}

iijima 2008/02/22(金) 16:24:24
> mapのpairのような振舞いさせたくて

素直にmapを使えば良いと思うが。。。

> find_if()を使ったらできそうなのですが

↓使ってみた。

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

struct Structure {
    int count;
    std::string yymmdd;
    Structure( int n = 0, std::string str = "" ) : count( n ), yymmdd( str ) {}
};

class CountEquals {
    const int& count;
public:
    CountEquals( const int& n ) : count( n ) {}
    bool operator()( const Structure& s ) {
        return s.count == count;
    }
};

const int MAGIC_NUM = 3;

int main ()
{
    std::string buff;
    std::vector< Structure > vec;

    for( int i = 0; i < 4; ++i ) {
        std::ostringstream oss;
        oss << i;
        vec.push_back( Structure( i, oss.str() + "日経過" ) );
    }

    for( std::vector< Structure >::size_type i = 0; i < vec.size(); ++i ) {
        std::cout << vec[ i ].count << " , " << vec[ i ].yymmdd << std::endl;
    }

    std::vector< Structure >::iterator pos
        = std::find_if( vec.begin(), vec.end(), CountEquals( MAGIC_NUM ) );

    if( pos != vec.end() ) {
        std::cout << "found! " << pos->yymmdd << std::endl;
    }
    else {
        std::cout << "not found...orz" << std::endl;
    }
}

とほほ 2008/02/22(金) 20:05:47
επιστημηさん、iijimaさん
お世話になります。
とほほです三日待って下さい脳内で咀嚼します。
関数オブジェクト(ファンクタ)が鬼門になっていて理解力がありません、
「Effective STL」を読み直します

iijima 2008/02/22(金) 21:44:27
> 関数オブジェクト(ファンクタ)が鬼門

私もはじめて「関数オブジェクト」という用語を見たときは?でしたが、「なんだ戻り値
がbool型の()演算子を定義しているだけじゃんか」と気がついてからは楽になりました。

言葉に惑わされる事なかれ。
関数オブジェクトとかファンクタなんていう用語を知らなくても、演算子の多重定義をし
っかり理解していれば鬼は出ません。
それに加えてテンプレートも勉強すればalgorithmもなんということはありません。

επιστημηさんのは難しそうに見えますが、基本を勉強した後にC++標準ライブラ
リを丹念に調べれば理解できるはずです。
# クラスの継承について十分に理解しているのは前提ですが。

余計なお世話ながらおまけのサンプル↓

// サンプル(1):簡単関数オブジェクト

struct IsEven {
    bool operator()( int n ) const {
        return n % 2 == 0;
    }
};

#include <iostream>

int main()
{
    int coll[] = { 0, 3, 2, 1, 4 };

    IsEven is_even; // 関数オブジェクト

    for( int i = 0; i < sizeof( coll ) / sizeof( coll[ 0 ] ); ++i ) {
        std::cout << coll[ i ] << "は";
        if( is_even( coll[ i ] ) ) { // ()演算子の定義により関数のように使える
            std::cout << "偶数" << std::endl;
        }
        else {
            std::cout << "奇数" << std::endl;
        }
    }
}


// サンプル(2):簡単アルゴリズム関数
// STLのアルゴリズム関数もやっていることはたいして変わらない。
// STLのソースも参照してみたら良いよ。

template < typename T, typename F >
T* find_if( T* beg, T* end, F& func )
{
    T* p;
    for( p = beg; p != end; ++p ) {
        if( func( *p ) ) {
            break;
        }
    }
    return p;
}

#include <string>
#include <iostream>

struct Pair {
    int count;
    std::string str;
    Pair( int n, std::string s ) : count( n ), str( s ){}
};

class CountEquals {
    const int& count;
public:
    CountEquals( const int& n ) : count( n ) {}
    bool operator()( const Pair& p ) const {
        return p.count == count;
    }
};

int main()
{
    Pair coll[] = {
        Pair( 3, "三" ),
        Pair( 4, "四" ),
        Pair( 1, "一" ),
        Pair( 2, "二" ),
        Pair( 0, "零" ),
    };

    Pair* beg = coll;
    Pair* end = coll + sizeof( coll ) / sizeof( coll[ 0 ] );

    CountEquals func( 2 );
    Pair* pos = find_if( beg, end, func );

    if( pos != end ) {
        std::cout << pos->count << " , " << pos->str << std::endl;
    }
    else {
        std::cout << "not found." << std::endl;
    }
}

とほほ 2008/02/23(土) 18:40:22
[[解決]]
iijimaさん、お世話になります
関数オブジェクトに関して、だいぶ理解が深まりました
といいますかiijimaさんが、噛み砕いて説明して下さったことが全てと理解し
単純に考えます。
STLは巧く使うとCの配列に比べメモリー管理も非常に楽でパワフルなのですが
私の場合少し高度なことを行おうとすると大概可読性の低い
何をやってるのか( ゜д゜)ポカーン …なコードか洗練されないものになってしまいます
そのようにならないため、関数オブジェクトやTemplateが使えると使えないのでは
雲泥の差が有るので、是非マスターして、一人前のC++使いになりたいと思います
沢山のサンプルコードありがとうございました。

古いスレッドには追加発言できません。