2013-04-05 2 views
0

У меня есть рекурсивная функция find(), которая пытается найти элемент с заданным ID. Ниже я извлек соответствующие части из класса, чтобы сделать пример компиляции:Рекурсивная функция не полностью рекурсирует объект/под-объекты

#include <iostream> 
#include <cstdarg> 
#include <cstdio> 
#include <string> 
#include <vector> 

class Item { 
private: 
    std::vector<Item> subitems; 

public: 
    std::wstring id; 

public: 
    Item() 
    : subitems(0), id(L"") {} 

    Item(const Item& rhs) 
    : subitems(rhs.subitems.size()) { 
     for (std::size_t i = 0; i < rhs.subitems.size(); ++i) 
      subitems[i] = rhs.subitems[i]; 
     id = rhs.id; 
    } 

    Item& operator==(const Item& rhs) { 
     if (this != &rhs) { 
      for (std::size_t i = 0; i < rhs.subitems.size(); ++i) 
       subitems[i] = rhs.subitems[i]; 
      id = rhs.id; 
     } 
     return *this; 
    } 

    std::vector<Item> getSubitems() { 
     return subitems; 
    } 

    Item addSubitems(Item * item ...) { 
     va_list args; 
     va_start(args, item); 
     for (Item * arg = item; arg != NULL; arg = va_arg(args, Item *)) { 
      subitems.push_back(*item); 
     } 
     va_end(args); 

     return *this; 
    } 

    Item addSubitems(std::vector<Item>& items) { 
     for (typename std::vector<Item>::value_type &item : items) { 
      subitems.push_back(item); 
     } 

     return *this; 
    } 

    static Item * find(int id, std::vector<Item>& items) { 
     std::wstring id_str = std::to_wstring(id); 
     std::wcout << "--> find id=" << id_str << std::endl; 
     std::wcout << "size of items=" << items.size() << std::endl; 
     for (typename std::vector<Item>::value_type &c : items) { 
      std::wcout << "it .. cur id=" << c.id << std::endl; 
      if (!c.id.empty() && c.id == id_str) { 
       std::wcout << "==> found" << std::endl; 
       return &c; 
      } 

      if (!(c.getSubitems()).empty()) { 
       std::wcout << "-> find " << id << " in subitems" << std::endl; 
       std::vector<Item> subcls = c.getSubitems(); 
       std::wcout << "size of subitems=" << subcls.size() << std::endl; 
       Item * sub = find(id, subcls); 
       if (sub != NULL) { 
        std::wcout << "==> found in subitems" << std::endl; 
        return sub; 
       } 
      } 
     } 
     return NULL; 
    } 
}; 

int main() { 
    Item c1; 
    c1.id = L"0"; 
    Item c2; 
    c2.id = L"1"; 
    Item c3; 
    c3.id = L"2"; 
    Item c4; 
    c4.id = L"3"; 
    //std::vector<Item> cll4({c4}); 
    //std::vector<Item> cll3({c3}); 
    //std::vector<Item> cll2({c2}); 

    c3.addSubitems(&c4, NULL); 
    c2.addSubitems(&c3, NULL); 
    c1.addSubitems(&c2, NULL); 

    //c1.addSubitems(cll2); 
    //c2.addSubitems(cll3); 
    //c3.addSubitems(cll4); 

    std::vector<Item> items({c1}); 

    Item * c = Item::find(2, items); 
    std::wcout 
     << "Found item=" 
     << ((c != NULL && c == &c3) ? "true" : "false") << std::endl; 
    std::wcout 
     << ((c != NULL) ? c->id : L"") << std::endl; 

    return 0; 
} 

создать несколько Items и добавить sub-Items к ним. Теперь я хочу иметь возможность искать идентификатор элемента и возвращать найденный объект или объект подпозиции с помощью рекурсивного метода find(). Если я добавляю элементы с addSubitems() (с переменными args), он найдет элемент, но не вернет объект (действительный) объект. Если я использую метод addSubitems, передавая вектор элементов, метод find() не полностью рекурсивно обрабатывает все подэлементы.

На самом деле я сижу на этой проблеме сейчас последние 4 часа, и у меня нет идей, это может быть простая вещь, которую я наблюдаю или пропускаю. Я добавил последовательности оператора конструктора/и оператора присваивания (просто чтобы увидеть, есть ли изменения в поведении), но нет. Не беспокойтесь о том, что идентификатор элемента является строковым типом (причина для последующей сериализации), этот класс находится на ранних этапах, поэтому я теперь выбрал тип строки.

Может ли кто-нибудь указать мне недостатки/проблемы, чтобы получить этот класс прямо! Большое спасибо заранее!

ответ

0

Ну, одна проблема с «он найдет элемент, но не вернет (действительный) объект объекта». is:

Вы отправляете Item * в метод addSubItems, а затем добавляете (* Item) к вектору; Это будет инициализировать копию c'tor, поэтому в дальнейшем, когда вы это сделаете, это & c == & c3, очевидно, это было бы ложно, поскольку, пока объекты INDEED идентичны, адреса не будут, так как они являются копиями одного другой.

Не то, что я понимаю, почему вы хотите скопировать, но решение будет либо тест

if (c == c3) -> activating the Item operator == 

ИЛИ выделить членов, сохранить

std::vector<Item*> subitems; 

, а затем попросить if (c == c3) -> asking about the addresses

+0

Спасибо за ввод. Да, действительно, после прочтения вашего ответа это кажется мне понятным. На данный момент я использую опцию номер 2 (вектор указателей), даже если я не очень доволен ею, но, развиваясь, я мог бы изменить несколько вещей. –

+0

убедитесь, что вы их распределите – Alon

Смежные вопросы