2015-06-22 47 views
1

我在reddits dailyprogrammer上經常遇到挑戰,要學習和練習C++。與上週challenge我被困在指針的東西。指針在第二次迭代後不再工作

挑戰是/是否創建了具有類別的待辦事項列表。我已經在previous challenge中執行了待辦事項列表部分,我從那裏開始工作。

這是我對這一挑戰的代碼:

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

class TodoItem; 
class Category{ 
public: 
    Category(std::string name) 
     : name(name) { 

    } 

    void addToCategory(TodoItem* item){ 
     items.push_back(item); 
    } 

    void removeFromCategory(const TodoItem* item){ 
     auto it = std::find(items.begin(), items.end(), item); 
     if (it != items.end()) 
     { 
      items.erase(it); 
     } 
    } 

    static Category combine(const Category &left, const Category &right){ 
     Category combined(left.getName() + ", " + right.getName()); 

     std::vector<TodoItem*> sortedLeft(left.items); 
     std::vector<TodoItem*> sortedRight(right.items); 

     std::sort(sortedLeft.begin(), sortedLeft.end()); 
     std::sort(sortedRight.begin(), sortedRight.end()); 

     std::set_intersection(sortedLeft.begin(), sortedLeft.end(), sortedRight.begin(), sortedRight.end(), std::back_inserter(combined.items)); 
     return combined; 
    } 

    std::string getName() const{ 
     return name; 
    } 

    bool operator==(const Category& a) const { 
     return a.getName() == getName(); 
    } 

    bool operator!=(const Category& a) const { 
     return a != *this; 
    } 

    bool operator<(const Category& a) const { 
     return this->getName() < a.getName(); 
    } 

    friend std::ostream& operator<<(std::ostream& os, const Category& category); 

private: 
    std::string name; 
    std::vector<TodoItem*> items; 
}; 

class TodoItem 
{ 
public: 
    TodoItem(const std::string &item) 
     : task(item) { 
    } 

    void update(const std::string &item){ 
     task = item; 
    } 

    std::string getTask() const{ 
     return task; 
    } 

    bool operator==(const TodoItem& a) const { 
     return a.getTask() == getTask(); 
    } 

    bool operator!=(const TodoItem& a) const { 
     return a != *this; 
    } 

    bool operator<(const TodoItem& a) const { 
     return this->getTask() < a.getTask(); 
    } 

    friend std::ostream& operator<<(std::ostream& os, const TodoItem& item) { 
     os << item.getTask() << std::endl; 
     return os; 
    } 

private: 
    std::string task; 
}; 


inline std::ostream& operator<<(std::ostream& os, const Category& category) { 
    os << "----" << category.getName() << "----" << std::endl; 
    for (auto &item : category.items){ 
     os << *item << std::endl; 
    } 
    return os; 
} 

class TodoList 
{ 
public: 

    void add(const std::string &task, const std::string &category = "No category"){ 

     Category* catPtr = nullptr; 

     for (size_t j = 0; j < categories.size(); j++) 
     { 
      if (categories[j] == Category(category)) 
      { 
       catPtr = &categories[j]; 
       break; 
      } 

     } 

     if (catPtr == nullptr) 
     { 
      categories.push_back(Category(category)); 
      catPtr = &categories[categories.size() - 1]; 
     } 


     for (size_t i = 0; i < items.size(); i++) 
     { 
      if (items[i] == TodoItem(task)) 
      { 
       catPtr->addToCategory(&items[i]); 
       return; 
      } 
     } 

     items.emplace_back(TodoItem(task)); 
     catPtr->addToCategory(&items[items.size() - 1]); 
    } 

    template<typename ... args> 
    void add(const std::string &task, const std::string &category, args... otherCategories){ 
     add(task, category); 
     add(task, otherCategories...); 
    } 

    void update(const std::string &oldTask, const std::string &newTask){ 
     auto itemIt = std::find(items.begin(), items.end(), TodoItem(oldTask)); 
     if (itemIt != items.end()) 
     { 
      itemIt->update(newTask); 
     } 
    } 


    template<typename ... args> 
    void viewList(std::ostream& os, args ... categoriesArgs) const{ 
     os << getCategory(categoriesArgs...); 
    } 

private: 
    Category getCategory(const std::string category) const{ 
     return *std::find(categories.begin(), categories.end(), Category(category)); 
    } 

    template<typename ... args> 
    Category getCategory(const std::string category, args ... categoriesArgs) const{ 
     return Category::combine(*std::find(categories.begin(), categories.end(), Category(category)), getCategory(categoriesArgs...)); 
    } 


    std::vector<TodoItem> items; 
    std::vector<Category> categories; 
}; 


int main(){ 
    TodoList list; 

    list.add("A pixel is not a pixel is not a pixel", "Programming"); 
    list.add("The Scheme Programming Language", "Programming"); 
    list.add("Memory in C", "Programming"); 
    list.add("Haskell's School of Music", "Programming", "Music"); 
    list.add("Algorithmic Symphonies from one line of code", "Programming", "Music"); 

    list.add("Modes in Folk Music", "Music"); 
    list.add("The use of the Melodic Minor Scale", "Music"); 

    list.viewList(std::cout, "Music"); 
    list.viewList(std::cout, "Programming"); 

    list.update("Algorithmic Symphonies from one line of code", "Algorithmic Symphonies from one line of code in C"); 
    list.viewList(std::cout, "Programming", "Music"); 

    return 0; 
} 

但是,當我執行它,我的方法TodoList::Add得到記性不好例外。

當我執行這些行時,指向前一個待辦事項的指針變得不可用。

 items.emplace_back(TodoItem(task)); 
     catPtr->addToCategory(&items[items.size() - 1]); 

有人可以向我解釋爲什麼會發生這種情況,我該如何解決這個問題? PS:我使用的是視覺工作室,不要認爲這很重要。

+4

如果沒有足夠的空間來放置新元素,'std :: vector'可能會重新分配它的數據。該重新分配將使向量中的所有當前指針和迭代器無效。我確信這裏有很多關於這個問題的重複。 –

+0

謝謝,這是否意味着我應該使用其他容器? – Frederiek

+0

這真的取決於你的用例。只有在調用addToCategory函數時,你也可以在所有項目添加到向量中之後有另一個循環(並且你確定不會再添加)。 –

回答

2

在對Joachim Pileborg的std::vector的內部工作反饋後,我意識到我需要其他容器結構。與結構std::forward_list我沒有我遇到過的問題。

相關問題