Removing blank elements from row vector

I am trying to create a small program that processes INI files for use in a later project, first by reducing its size after loading it into memory. Thus,

where vLine is a vector containing the contents of the file

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

When printing vLine, I will remain spaces where there would be a line starting with a colon, for example

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

Using the resize () parameter allows you to remove the last item from the list, rather than removing these empty parts. The same problem exists when I delete lines containing only spaces with erase ().

Is it possible to remove these empty elements while maintaining the vLine order?

(Sorry for not using iterators in this.)

+7
source share
3 answers

It:

 vLine[i].erase(); 

does not erase vLine[i] from the vector. The expression vLine[i] returns a reference to the element in index i . Assuming vLine is of type std::vector<std::string> , calling the erase() function actually calls string::erase() on the element, not vector::erase() on the vector. Everything you do makes this particular element empty.

What you might want is something like this:

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

This actually removes the element from the vector. Now this invalidates all current iterators for the vector, and the indexes will no longer be right. This is a situation where you really need to use iterators.

 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; } } 

But there is an even simpler way to do this: use the standard std::remove_if() algorithm with a functor, then call 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()); 

If you can use the C ++ 11 compiler, then you can also use lambda expressions even more concise.

+9
source

The problem is your logic for deleting items. When you come across an element with index i that you want to erase, you clear its value, but you do not remove it from the vector.

The standard and easy way to do what you want to do is std::remove_if :

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

Use erase / remove-idiom, preferably with lambda from C ++ 11:

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

All Articles