2011-10-07 67 views
7

我正在嘗試製作一個小程序,該程序處理INI文件,以便在稍後的項目中使用,首先通過減小其大小,一旦加載到內存中。因此,從字符串矢量中刪除空元素

其中U電源是包含文件內容

for (unsigned int i = 0; i < vLine.size(); i++) 
{ 
    if (!vLine[i].find(';', 0)) 
    { 
     vLine[i].erase(); 
    } 
} 

在打印時VLINE的載體,我會留下空間,其中一旦與分號開頭的行中存在,如

1.  
2. property 
3. property 
4. 
5. property 

使用resize()似乎從列表中刪除最後一個元素,而不是刪除這些空白部分。同樣的問題存在於我用erase()刪除只包含空格的行。

是否可以在保留vLine的順序的同時刪除這些空元素?

(道歉在此不使用迭代器。)

+0

回覆:(道歉在此不使用迭代器) - 爲什麼不使用迭代器? –

+0

缺乏正確使用的知識。似乎(似乎?)有可能在沒有它們的情況下做到這一點。 – JGrey

+1

您可以刪除的矢量線條,而不是僅僅刪除該字符串的內容(這是什麼'VLINE [I] .erase()'呢,不是嗎?叫'vLine.erase()'因爲從'VECTOR'擦除然後重寫文件了。一個慣用的方式做,這是C++的[擦除remove慣用法(http://en.wikipedia.org/wiki/Erase-remove_idiom),雖然你可能需要使用'的std ::的remove_if ''從'使用條件。 – birryree

回答

8

此:

vLine[i].erase(); 

不從矢量擦除vLine[i]。表達式vLine[i]返回索引爲i的元素的引用。因此,假設vLine的類型爲std::vector<std::string>,函數調用erase()實際上在該元素上調用string::erase(),而不是向量上的vector::erase()。你所做的只是將這個特定的元素留空。

你可能需要的是這樣的:

vLine.erase(vLine.begin() + i); 

這實際上刪除Vector中的元素。現在,這會使所有當前迭代器無效,並且索引將不再正確。這是你真的需要使用迭代器的情況。

std::vector<std::string>::iterator i = vLine.begin(); 
while(i != vLine.end()) 
{ 
    if(i->find(';', 0) != std::string::npos) 
    { 
     i = vLine.erase(i); 
    } 
    else 
    { 
     ++i; 
    } 
} 

但還有一種更簡單的方式做到這一點:使用標準算法std::remove_if()用仿函數,然後調用vLine.erase()

struct HasSemicolon 
{ 
    bool operator()(const std::string& s) 
    { 
     return s.find(';', 0) != std::string::npos; 
    } 
}; 

// ... 

vLine.erase(std::remove_if(vLine.begin(), vLine.end(), HasSemicolon()), vLine.end()); 

如果你可以使用C++編譯器11,那麼你也可以使用lambda表達式會更加簡潔。

+0

非常感激,在硅片,我會花時間去學習的迭代器和相應地改變我的應用程序的時間。 – JGrey

+0

你能使用C++ 11 lambda表達式添加一個例子嗎?我一直在努力現在弄明白了一個小時的大部分時間,但我在讀C++文檔可怕。 –

+0

@QPaysTaxes http://en.cppreference.com/w/cpp/algorithm/remove與拉姆達的例子。 – arekolek

4

使用擦除/卸下成語,優選具有C++ 11拉姆達:

foo.erase(std::remove_if(foo.begin(), foo.end(), 
         [](const std::string& s) 
         { return s.find(';', 0); })); 
7

的問題是在邏輯用於除去的元素。當您遇到要清除索引i處的元素時,請清除其值,但不要將其從矢量中刪除。

標準和簡單的方法做你想做的事是std::remove_if

vLine.erase(
    std::remove_if(
     vLine.begin(), 
     vLine.end(), 
     [](std::string const& s) { return s.size() != 0 && s.front() == ';'; }), 
    vLine.end());