Как условно удалить элемент из списка с помощью итератора?

Проблема:

Я пишу простое приложение для управления файлами. В этой программе у меня есть класс «Каталог»:

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

и связанный список объектов каталога:

list<Directory*> DirectoryList;

Я хочу реализовать "rm -r directorypath" Команда оболочки в Linux, поэтому мне нужно просмотреть список и удалить каталог «directorypath» и все его подкаталоги. Проблема в том, что я не знаю, как просмотреть список ссылок и удалить все каталоги, родительский каталог которых — «directorypath». Я попробовал эти два метода:

способ 1:

Этот метод сталкивается с ошибкой во время выполнения, поскольку он не может получить доступ к списку после первого удаления.

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

метод 2:

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

этот метод может получить доступ ко всем элементам отлично даже после удаления, но я не знаю, как это проверить, если условие с помощью итератора it:

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

3

Решение

Ваш способ 1 терпит неудачу, потому что std::list.remove(val) удаляет все элементы в вашем списке, которые сравниваются равными val. Вы звоните один раз, и все готово. for() цикл не должен быть там, это не тот способ, которым он предназначен для использования. Хороший пример Вот.

Обратите внимание, что этот метод изменит ваш контейнер и его размер. Вы должны быть осторожны и убедиться, что ваши итераторы остаются в силе после вызова erase, Мне кажется, что итераторы действительно становятся инвалидами, и поэтому вы получаете ошибки.

Ваш способ 2 выглядит почти нормально. Прежде всего, совет парня niceguy, чтобы проверить условие:

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

Теперь имейте в виду, что стирание it обновит итератор, чтобы он указывал на местоположение после удаленного итератора. Это считается одним обновлением вашего итератора, it, Это будет дополнительно обновлено в for цикл, но это не то, что вам нужно (то есть два обновления за итерацию означают, что вы пропускаете некоторые элементы). Вы можете попробовать что-то вроде этого:

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

Другие решения


По вопросам рекламы [email protected]