How can I conditionally remove an item from a list using an iterator?

Problem:

I am writing a simple file manager application. In this program, I have a "Directory" class:

class Directory
{
public:
    Directory(string address, string directoryname)
    {
        this->path = address;
        this->name = directoryname;
    }
    string GetFullPath(){ return path == "/" ? path + name : path + "/" + name; }
    string path;
    string name;
    string user;
};

      

and a linked list of directory objects:

list<Directory*> DirectoryList;

      

I want to implement a shell command "rm -r directorypath"

in linux, so I need to list and delete the "directorypath" and all its subdirectories. The problem is that I don't know how to go through the link list and delete all directories whose parent directory is "directory path". I've tried these two methods:

method 1:

This method encounters a runtime error because after the first delete it can no longer access the list.

for (auto address : DirectoryList)
        if (address->GetFullPath() == directorypath)
        {
            for (auto subdirectory : DirectoryList)
            if (subdirectory ->path == address->GetFullPath())
                DirectoryList.remove(subdirectory );
        }

      

method 2:

for (auto address : DirectoryList)
        if (address->GetFullPath() == directorypath)
        {
            for (auto it = DirectoryList.begin(); it != DirectoryList.end();)
                it = DirectoryList.erase(it);
            return true;
        }

      

this method can access all elements even after deletion, but I don't know how to test this if condition with an iterator it

:

if (subdirectory ->path == address->GetFullPath())

      

+3


source to share


1 answer


Your method 1 doesn't work because it std::list.remove(val)

removes all elements in your list that compare against val. You call it once and you're done. The loop for()

shouldn't be there, this is not the way it was intended to be used. A good example is here .

Please note that this method will change your container and its size. You have to be careful and make sure your iterators are still valid after being called erase

. I feel like it is indeed the iterators becoming invalid and why you are getting errors.

Your method 2 looks almost normal. First of all, a hovering tip to check the condition:



if ((*it).path == address->GetFullPath())

      

Now, note that erasing will it

update the iterator to point to the location after the iterator is removed. This is one upgrade your iterator it

. It will update further in the loop for

, but that's not what you want (i.e. two updates per iteration means you are missing some elements). You can try something like this instead:

auto it = DirectoryList.begin()
while (it != DirectoryList.end())
{
   if ((*it).path == address->GetFullPath())
       DirectoryList.erase(it);
}

      

+1


source







All Articles