Перебор списка объектов c ++ - PullRequest
0 голосов
/ 06 сентября 2018

В основном я создаю основную программу оболочки для проекта класса. Я застрял на итерации файлов / папок в каталоге.

Моя ошибка в функции DisplayDirectoryContents ()

class Directory 
{
private:
map<string, pair<list<Folder>, list<File> > > directoryContents;
string directoryPath;

public:
list<Folder> getFolders() {return directoryContents[directoryPath].first;}
list<File> getFiles() {return directoryContents[directoryPath].second;}
string getDirectoryPath() {return directoryPath;}

Directory() 
{
    directoryPath = "root/"; 
    File *file = new File("Test");
    directoryContents[directoryPath].second.push_back(*file);
}
void DisplayDirectoryContents()
{
    // Get files and folders from directory
    list<File> files = this->getFiles();

    for(int i = 0; i < files.size(); i++)
    {
        cout << files->getFileName(); << Error here
    }

}
};

Я пытался настроить эту функцию несколькими различными способами, но я не могу найти правильный код, чтобы заставить ее работать.

Я бы подумал, что это сработает, но каждый раз, когда я пытаюсь связываться с функцией DisplayDirectoryContents (), это вызывает ошибки. У кого-нибудь есть какие-нибудь советы, которые я могу попытаться исправить? Спасибо

class File
{
string fileName;
string fileTime;
public:
string getFileTime(){return fileTime;}
string getFileName(){return fileName;}

void setFileTime(){time_t now = time(NULL);
                fileTime = ctime(&now);} 
void setFileName(string newFileName){fileName = newFileName;}
File(){}
File(string fName)
{
    fileName = fName;
    time_t now = time(NULL);
    fileTime = ctime(&now);
}
void MakeFile(string fName);
void RemoveFile(string fName); 
};

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Расширение до R Саху * ответ :

Причина, по которой вы не можете выполнить итерацию с использованием исходного цикла, заключается в том, что std::list не предлагает оператора индекса (вам нужно будет использовать std::vector вместо этого).

Альтернативный подход к диапазону, основанный на цикле (который я предпочел бы, хотя, если у вас нет особых причин для этого) & ndash; или путь, если у вас нет C ++ 11 в наличии & ndash; использует итераторы:

for(std::list<File>::iterator i = files.begin(); i != files.end; ++i)
{
    std::cout << i->getFileName();
}

С C ++ 11 вы можете иметь for(auto i = files.begin(); ....

Варианты использования для использования цикла итератора даже в C ++ 11 могут сравнивать элементы с их наследниками:

// check for empty list first, as std::prev would fail on!)
for(auto i = files.begin(); i != std::prev(files.end()); ++i)
{
    if(someCondition(*i, *std::next(i))
    {
        // do something else
    }
}

Уже есть std::remove_if для, и вы должны предпочесть его (вместе с лямбдой; но не забудьте применить erase впоследствии, см. стереть -remove-идиома !), так что просто для иллюстрации; начиная с более простого подхода:

for(auto i = files.begin(); i != files.end(); ) // no ++i (!)
{
    if(condition)
    {
        i = files.erase(i);
        // fine for std::list; with std::vector, if removing more
        // than one single element, we'd move or even copy subsequent
        // elements multiple times, which is quite inefficient
    }
}

Улучшенный вариант (это то же самое, что делает std::remove_if):

auto pos = files.begin();
for(auto i = files.begin(); i != files.end(); ++i)
{
    if(!condition)
    // ^ (!)
    {
        *pos++ = std::move(*i);
    }
}
// here, std::remove_if already stops, but returns pos...
files.erase(pos, files.end());

Минимальная проблема может остаться с операторами перемещения или копирования, которые не обрабатывают самоопределение правильно, что будет покрыто if(!condition && i != pos).

0 голосов
/ 06 сентября 2018

Если вы можете использовать C ++ 11 или выше, вы можете использовать цикл диапазона for для перебора содержимого списка.

void DisplayDirectoryContents()
{
    // Get files and folders from directory
    list<File> files = this->getFiles();

    // Iterate over each item in the list.
    // Use a reference to avoid copying of the items.
    for ( File& file : files )
    {
        cout << file.getFileName();
    }
}
...