2011-10-07 99 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());