Проблема:
Я пишу простое приложение для управления файлами. В этой программе у меня есть класс «Каталог»:
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())
Ваш способ 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);
}