1

具体的には、複数の文字列オブジェクトデータメンバー(NID、customerNumber、studentNumber、fName、lName)を持つクラスのオブジェクトのリストがあります。

次のコードを再利用して、検索対象のデータメンバーがNIDであるか、クラスの他の文字列データメンバーであるかに関係なく、検索キーに一致するノードを検索します。

nodePtr = firstPtr;
for(; nodePtr != NULL && nodePtr->str != str; nodePtr = nodePtr->nextPtr);

if(nodePtr != NULL)
    //the nodePtr points to the node that matches the search key
else
    //no node matched the search key

PHPコードの場合、変数の値を別の名前として使用できます。

$node->${$var}

しかし、C ++ではコードを再利用する方法はありますか?

4

5 に答える 5

2

これを行う最も柔軟な方法は、述語をテンプレート パラメーターとして提供することです。

template <typename Pred>
Node * find_if(Node * node, Pred pred) {
    for (; node && !pred(node); node = node->next);
    return node;
}

C++11 では、ラムダで呼び出すことができます。

if (Node * node = find_if(first, [&](Node * n){return n->NID == nid;})) {
    // node points to the matching node
} else {
    // not found
}

または、過去の時代に行き詰まっている場合は、関数オブジェクト:

struct CompareNID {
    CompareNID(std::string nid) : nid(nid) {}
    bool operator() {Node * n) {return n->NID == nid;}

    std::string nid;
};

Node * node = find_if(first, CompareNID(nid));

または、すべてのフィールドが文字列であるため、メンバーポインターを使用して簡潔さのために柔軟性を犠牲にして、PHP の例に似たものを与えることができます。

Node * find(Node * node, std::string Node::*member, std::string const & value) {
    for (; node && node->*member != value; node = node->next);
    return node;
}

Node * node = find(first, &Node::NID, nid);
于 2013-01-29T11:43:17.670 に答える
2

に似ていstd::find_ifます:

template<typename N, typename P>
N* my_find_if(const N* head, P pred)
{
    N* ptr;
    for (ptr = head; ptr != nullptr && !pred(ptr); ptr = ptr->nextPtr)
        ;

    return ptr;
}

次のように呼び出すことができます。

my_find_if(firstPtr,
    [](Node* node){ return node->str == str; });

ラムダを必要な式に変更します。

もちろん、独自のリストを作成するのではなく、標準のコンテナーを使用することをお勧めします。std::find_if次に、代わりに標準を使用できます。

于 2013-01-29T11:38:52.390 に答える
1

はい、2 つのラムダ (C++11) または実行可能なオブジェクト (C++03) を「検索」アルゴリズムに渡したいと考えています。

C++03 では、「見つかった」ケース用と「見つからない」ケース用の 2 つのブースト関数を渡すことができます。

void search( std::string str, 
            boost::function<void()> ifFound, 
           boost::function<void()> ifNotFound )
{
      //search
     if( nodePtr != NULL )
     {
          ifFound();
     }
     else
     {
          ifNotFound();
     }
}

一致する関数シグネチャを選択しますが、それが動的関数を渡す方法です。

std::functionの代わりに使用できますboost::function

検索自体を柔軟にしたい場合、つまり、オブジェクトのどの部分を一致させようとしているかについては、動的述語も使用してください。

void search( Pred pred// , ifFound, ,ifNotFound )
{
     if( pred( nodePtr ) ) // then it is found
}

ご覧のとおり、述語はノード ポインターを取り、true/false を返します。したがって、さまざまな述語を使用して、さまざまなデータ メンバーに一致させることができます。

ただし、「再利用可能なコード」の概念が本当に好きな場合は、標準ライブラリを使用することをお勧めします。

リストが長く、これらの検索を継続的に行っている場合、手動検索は遅く、boost::multi_indexさまざまなフィールドで log-N 時間のルックアップを作成するために を使用できます。

于 2013-01-29T11:32:26.260 に答える
0

もう 1 つの方法は、メンバーへのポインターを使用することです (すべてのメンバーが同じ型である場合にのみ可能です)。

struct Item {
    std::string NID,
                customerNumber,
                studentNumber,
                fName,
                lName;
};

typedef std::vector<Item>::iterator nodePtr;

typedef std::string Item::* MemberPtr;

struct List {
    std::vector<Item> list;

    nodePtr search(const std::string& str, MemberPtr mem_ptr)
    {
        // this is the code you want to reuse, I took the liberty and used
        // standard lib's algorithm
        return std::find_if(list.begin(), list.end(),
                            [&](const Item& item){ return str == item.*mem_ptr; });
        // will return list.end() if it doesn't find anything
    }
};

int main()
{
    List lst;
    lst.search("John", &Item::fName);
    lst.search("Doe", &Item::lName);
    lst.search("42", &Item::customerNumber);
}

これは、PHP の例に最も近いと思います。

于 2013-01-29T11:47:54.857 に答える
0

メンバーへのポインターを使用したい場合があります。

typedef string Node::*NodeStringPtr;
NodeStringPtr nodeStrPtr = nullptr;
std::vector<NodeStringPtr> nodeStrings {&Node::NID, &Node::str, &Node::fName};
for (auto& ptr : nodeStrings)
{
  nodePtr = firstPtr;
  for (; nodePtr != NULL && nodePtr->*ptr != str; nodePtr = nodePtr->nextPtr);
  if (nodePtr)
  {
    nodeStrPtr = ptr;
    break;
  }
}

if(nodePtr != NULL)
    //the nodePtr matches the search key, nodeStrPtr matches the element
else
    /* ...*/
于 2013-01-29T11:45:42.857 に答える