2014-03-28 42 views
2

所以我在我的班級裏面找到了一種方法,這個班級應該做的是檢查我在.h文件中的矢量是否具有值在double low之間& double high然後刪除這些,最後返回多少「空格「被刪除向量迭代器擦除給我一個運行時錯誤?

所以我嘗試了一些東西,我總是得到運行時錯誤,它似乎是在for循環,但我無法弄清楚爲什麼。

這裏是我試過,

首先,我想只是做我覺得它的工作方式:

int datastorage::eraseDataPointsBetween(double low,double high) 
{ 
    int antal = 0; 
    for (vector<double>::iterator i = data_.begin(); i !=data_.end();i++) 
    { 
     if (*i >=low && *i <=high) 
     { 
      data_.erase(i); 
      antal++; 
     } 

    } 
    return antal; 
} 

但後來我試着做一些調試和我看得出來,它實際上並沒有讓它變成這樣,因爲當某些東西被刪除時它仍然會增加(所以如果我們刪除「space 2」,它實際上會在下次檢查空間4時(因爲在擦除之後,第3個點成爲第2個點) ))

所以我試圖改變它到這個

int datastorage::eraseDataPointsBetween(double low,double high) 
{ 
    int antal = 0; 
    for (vector<double>::iterator i = data_.begin(); i !=data_.end();) 
    { 
     if (*i >=low && *i <=high) 
     { 
      data_.erase(i); 
      antal++; 
     } 
     else 
      i++; 
    } 
    return antal; 
} 

凡只遞增i每當我不刪除空格(所以如果我刪除「空間2」,它會檢查新的「空間2」下一次運行)

這也給了我語法錯誤expression: vector iterators incompatible

希望能幫到你,因爲我幾乎失去了

,所以你不能用它的呼叫後,進行消除
+0

如何定義'data_'類型? – billz

+0

vector data_; – Sumsar1812

+0

但我有一些其他的功能,把值放入向量,這是行不通的,我可以發佈它們,但並不認爲它們是需要的 – Sumsar1812

回答

5

vector::erase無效迭代器。 你應該從vector抹去這樣:

int datastorage::eraseDataPointsBetween(double low, double high) { 
    int antal = 0; 
    for(vector<double>::iterator i = data_.begin(); i !=data_.end()) 
    { 
    if((*i >= low) && (*i <= high)) 
    { 
     i = data_.erase(i); // new (valid) iterator is returned 
     ++antal; 
    } 
    else 
    { 
     ++i; 
    } 

    return antal; 
} 
+0

這工作完美,擦除返回新的迭代器,因爲我可以做我= data_.erase(我)? 也感謝您的回答,我真的很感激它 – Sumsar1812

+0

是的,我會,我只是想確定我的理解正確(我在上面的評論中提到的是真實的?) – Sumsar1812

+1

是的,這是正確的 – 4pie0

2

您應該使用的remove_if()和擦除。這比編寫自己的循環更穩定的原因很簡單 - 使用無效迭代器不會遇到麻煩。

#include <algorithm> 
#include <vector> 

struct IsBetween 
{ 
    double low, high; 
    IsBetween(double l, double h) : low(l), high(h) {} 
    bool operator()(double d) const { return d >= low && d <= high; } 
}; 

void datastorage::eraseDataPointsBetween(double low,double high) 
{ 
    std::vector<double>::iterator it = std::remove_if(data.begin(), data.end(), IsBetween(low, high)); 
    data.erase(it, data.end()); 
} 

沒有循環,並注意使用remove_if()函數對象IsBetween。

底線是,您應該最小化嘗試編寫循環,以便在容器上循環時清除容器中的項目。有remove_if(),remove(),partition()等將您想要關注的數據移動到容器的一端。

儘管你會看到在循環時擦除迭代器的答案,而且看起來很安全,但有多少人會記住返回的規則,或者更確切地說,是不正確地編寫循環? (即使有經驗的C++程序員也可能在第一次切割時錯誤地寫入循環)。所以使用這些算法爲你做這個工作。

對於remove_if(),「壞」數據將移動到最後,您現在可以輕鬆擦除它們。