我正在尝试创建一个处理INI文件的小程序,以便在以后的项目中使用,首先通过在加载到内存后减小其大小。因此,
其中vLine是包含文件内容的向量
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 :(得分:10)
此:
vLine[i].erase();
不会从矢量中删除vLine[i]
。表达式vLine[i]
返回对索引i
处的元素的引用。因此,假设vLine
的类型为std::vector<std::string>
,函数调用erase()
实际上会调用元素上的string::erase()
,而不是向量上的vector::erase()
。您所做的只是将该特定元素留空。
你可能想要的是这样的:
vLine.erase(vLine.begin() + i);
这实际上从向量中删除了元素。现在,这确实使向量的所有当前迭代器无效,并且索引将不再正确。在这种情况下,您确实需要使用迭代器。
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表达式来更简洁。
答案 1 :(得分:8)
问题在于您删除元素的逻辑。当您遇到要删除的索引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());
答案 2 :(得分:5)
使用erase / remove-idiom,最好使用C ++ 11中的lambda:
foo.erase(std::remove_if(foo.begin(), foo.end(),
[](const std::string& s)
{ return s.find(';', 0); }));