Снова используйте тот же самый код, чтобы сделать ту же самую логику на различных элементах данных objcets в списке

определенно у меня есть список объектов класса с многократными участниками данных объектов последовательности (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++ должен там так или иначе снова использовать код?

1
@JoachimPileborg, Как я мог использовать шаблоны? templates' параметры - заполнители для типов не имена переменной!
добавлено автор MTVS, источник
@JoachimPileborg, Как я мог использовать шаблоны? templates' параметры - заполнители для типов не имена переменной!
добавлено автор MTVS, источник
@JoachimPileborg, Как я мог использовать шаблоны? templates' параметры - заполнители для типов не имена переменной!
добавлено автор MTVS, источник
Макрос препроцессора? Шаблоны?
добавлено автор Some programmer dude, источник
Макрос препроцессора? Шаблоны?
добавлено автор Some programmer dude, источник
Макрос препроцессора? Шаблоны?
добавлено автор Some programmer dude, источник
@csstd: параметры Шаблона могут быть ценностями, а не типами; в частности, они могут быть указателями на участников класса, которые были бы одним способом решить вашу проблему - если область, которую вы хотите, всегда известна во время компиляции. Иначе указатель на участника (или, более гибко, функциональный объект предиката) может быть передан как аргумент функции.
добавлено автор Mike Seymour, источник
@csstd: параметры Шаблона могут быть ценностями, а не типами; в частности, они могут быть указателями на участников класса, которые были бы одним способом решить вашу проблему - если область, которую вы хотите, всегда известна во время компиляции. Иначе указатель на участника (или, более гибко, функциональный объект предиката) может быть передан как аргумент функции.
добавлено автор Mike Seymour, источник
@csstd: параметры Шаблона могут быть ценностями, а не типами; в частности, они могут быть указателями на участников класса, которые были бы одним способом решить вашу проблему - если область, которую вы хотите, всегда известна во время компиляции. Иначе указатель на участника (или, более гибко, функциональный объект предиката) может быть передан как аргумент функции.
добавлено автор Mike Seymour, источник

14 ответы

Подобный станд.:: find_if:

template
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; });

Изменитесь лямбда к любому выражению вам нужно.

Конечно, я рекомендовал бы вам использовать стандартные контейнеры вместо того, чтобы создать ваш собственный список. Тогда вы могли использовать стандарт станд.:: find_if вместо этого.

2
добавлено
Как некоторый промежуточный шаг между вращением его собственного списка и использованием стандартного контейнера можение хочет рассмотреть написание типа iterator для его таможенного списка, в этом случае он мог также использовать стандартные алгоритмы.
добавлено автор Frerich Raabe, источник

Подобный станд.:: find_if:

template
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; });

Изменитесь лямбда к любому выражению вам нужно.

Конечно, я рекомендовал бы вам использовать стандартные контейнеры вместо того, чтобы создать ваш собственный список. Тогда вы могли использовать стандарт станд.:: find_if вместо этого.

2
добавлено
Как некоторый промежуточный шаг между вращением его собственного списка и использованием стандартного контейнера можение хочет рассмотреть написание типа iterator для его таможенного списка, в этом случае он мог также использовать стандартные алгоритмы.
добавлено автор Frerich Raabe, источник

Подобный станд.:: find_if:

template
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; });

Изменитесь лямбда к любому выражению вам нужно.

Конечно, я рекомендовал бы вам использовать стандартные контейнеры вместо того, чтобы создать ваш собственный список. Тогда вы могли использовать стандарт станд.:: find_if вместо этого.

2
добавлено
Как некоторый промежуточный шаг между вращением его собственного списка и использованием стандартного контейнера можение хочет рассмотреть написание типа iterator для его таможенного списка, в этом случае он мог также использовать стандартные алгоритмы.
добавлено автор Frerich Raabe, источник

Самый гибкий способ сделать это должно обеспечить предикат как параметр шаблона:

template 
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));

или, так как все ваши области - последовательности, вы могли пожертвовать гибкостью за tersity использование членских указателей, дав что-то подобное вашему примеру 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);
2
добавлено
просто пропущенный второй параметр в find_if списке параметров
добавлено автор MTVS, источник
@csstd: Хорошо определенный. Я думаю it' s исправляют теперь.
добавлено автор Mike Seymour, источник

Самый гибкий способ сделать это должно обеспечить предикат как параметр шаблона:

template 
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));

или, так как все ваши области - последовательности, вы могли пожертвовать гибкостью за tersity использование членских указателей, дав что-то подобное вашему примеру 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);
2
добавлено
просто пропущенный второй параметр в find_if списке параметров
добавлено автор MTVS, источник
@csstd: Хорошо определенный. Я думаю it' s исправляют теперь.
добавлено автор Mike Seymour, источник

Самый гибкий способ сделать это должно обеспечить предикат как параметр шаблона:

template 
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));

или, так как все ваши области - последовательности, вы могли пожертвовать гибкостью за tersity использование членских указателей, дав что-то подобное вашему примеру 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);
2
добавлено
просто пропущенный второй параметр в find_if списке параметров
добавлено автор MTVS, источник
@csstd: Хорошо определенный. Я думаю it' s исправляют теперь.
добавлено автор Mike Seymour, источник

Да, вы хотите пройти в 2 лямбдах (C++ 11) или работоспособные объекты (C++ 03) в ваш алгоритм "находки".

С C++ 03 вы могли бы пройти в 2 функциях повышения, один для "найденного" случая и один для "не найденного" случая.

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

Выберите свои подписи функции, чтобы соответствовать, но это - то, как вы проходите в динамических функциях.

Вы могли использовать станд.:: функция вместо повышение:: функция .

Если это - поиск себя, вы хотите сделать гибким, т.е. какой части вашего объекта вы пытаетесь соответствовать, используйте также динамический предикат.

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

Предикат, как вы видите, возьмет указатель узла и возвратится истинный/ложный. Таким образом различные предикаты использовались бы, чтобы соответствовать различным элементам данных.

Если бы вам действительно нравится понятие "повторно используемого кода", хотя, я предложил бы, чтобы вы пользовались стандартной библиотекой.

Если ваши списки длинны, и вы все время делаете эти поиски, ручной поиск медленный, и вы могли использовать повышение:: multi_index , чтобы создать поиски времени регистрации-N на ваших различных областях.

1
добавлено

Да, вы хотите пройти в 2 лямбдах (C++ 11) или работоспособные объекты (C++ 03) в ваш алгоритм "находки".

С C++ 03 вы могли бы пройти в 2 функциях повышения, один для "найденного" случая и один для "не найденного" случая.

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

Выберите свои подписи функции, чтобы соответствовать, но это - то, как вы проходите в динамических функциях.

Вы могли использовать станд.:: функция вместо повышение:: функция .

Если это - поиск себя, вы хотите сделать гибким, т.е. какой части вашего объекта вы пытаетесь соответствовать, используйте также динамический предикат.

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

Предикат, как вы видите, возьмет указатель узла и возвратится истинный/ложный. Таким образом различные предикаты использовались бы, чтобы соответствовать различным элементам данных.

Если бы вам действительно нравится понятие "повторно используемого кода", хотя, я предложил бы, чтобы вы пользовались стандартной библиотекой.

Если ваши списки длинны, и вы все время делаете эти поиски, ручной поиск медленный, и вы могли использовать повышение:: multi_index , чтобы создать поиски времени регистрации-N на ваших различных областях.

1
добавлено

Да, вы хотите пройти в 2 лямбдах (C++ 11) или работоспособные объекты (C++ 03) в ваш алгоритм "находки".

С C++ 03 вы могли бы пройти в 2 функциях повышения, один для "найденного" случая и один для "не найденного" случая.

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

Выберите свои подписи функции, чтобы соответствовать, но это - то, как вы проходите в динамических функциях.

Вы могли использовать станд.:: функция вместо повышение:: функция .

Если это - поиск себя, вы хотите сделать гибким, т.е. какой части вашего объекта вы пытаетесь соответствовать, используйте также динамический предикат.

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

Предикат, как вы видите, возьмет указатель узла и возвратится истинный/ложный. Таким образом различные предикаты использовались бы, чтобы соответствовать различным элементам данных.

Если бы вам действительно нравится понятие "повторно используемого кода", хотя, я предложил бы, чтобы вы пользовались стандартной библиотекой.

Если ваши списки длинны, и вы все время делаете эти поиски, ручной поиск медленный, и вы могли использовать повышение:: multi_index , чтобы создать поиски времени регистрации-N на ваших различных областях.

1
добавлено

Возможно, вы хотите использовать указатель на участников:

typedef string Node::*NodeStringPtr;
NodeStringPtr nodeStrPtr = nullptr;
std::vector 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
    /* ...*/
0
добавлено

Возможно, вы хотите использовать указатель на участников:

typedef string Node::*NodeStringPtr;
NodeStringPtr nodeStrPtr = nullptr;
std::vector 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
    /* ...*/
0
добавлено

Еще один путь состоит в том, чтобы использовать указатели на участников (только возможный, если все участники имеют тот же самый тип):

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

typedef std::vector::iterator nodePtr;

typedef std::string Item::* MemberPtr;

struct List {
    std::vector 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.

0
добавлено

Еще один путь состоит в том, чтобы использовать указатели на участников (только возможный, если все участники имеют тот же самый тип):

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

typedef std::vector::iterator nodePtr;

typedef std::string Item::* MemberPtr;

struct List {
    std::vector 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.

0
добавлено

Еще один путь состоит в том, чтобы использовать указатели на участников (только возможный, если все участники имеют тот же самый тип):

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

typedef std::vector::iterator nodePtr;

typedef std::string Item::* MemberPtr;

struct List {
    std::vector 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.

0
добавлено
pro.cxx
pro.cxx
3 049 участник(ов)

C/C++ chat 0. Простые вопросы, лабы и о IDE — в чат новичков @supapro 1. Не хамим, не переходим на личности, не вбрасываем утверждения без доказательств 2. No Ads, offtop, flood Объявления о вакансиях и евенты - в лс @AlexFails https://t.me/ProCxx/259155

supapro.cxx
supapro.cxx
1 925 участник(ов)

Чат для тех, кто немного знает C++, простые вопросы по реализации, синтаксису и ide – сюда, а для другого есть: /Главный чат по серьезным вопросам — @ProCxx /Чат по обсуждению всего — @fludpac

C++ Russia
C++ Russia
384 участник(ов)

Сообщество разработчиков C++ в Telegram.

cxx.Дискуссионная
cxx.Дискуссионная
298 участник(ов)

это не двач, общайтесь вежливо; разговор на почти любые темы; Не согласны с баном? В лс @AlexFails, @ivario

C++ для маленьких и тупых
C++ для маленьких и тупых
105 участник(ов)

Лоу левел (по среднему IQ участников) чатик ExtremeCode @extremecode Флудилка @extremecode_rest