简体   繁体   English

迭代对象列表 C++

[英]Iterating over a list of objects c++

Basically I am creating a basic shell program for a class project.基本上我正在为一个类项目创建一个基本的shell程序。 I am stuck on iterating through the files/folders within a directory.我坚持遍历目录中的文件/文件夹。

My error is in the function DisplayDirectoryContents()我的错误是在函数 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
    }

}
};

I've tried setting this function up a few different ways but I can't seem to get the right kind of code to make it work.我试过用几种不同的方式设置这个函数,但我似乎无法得到正确的代码来使它工作。

I would think this would work but it's throwing me errors everytime I try and mess with the DisplayDirectoryContents() function.我认为这会奏效,但每次我尝试使用 DisplayDirectoryContents() 函数时都会出错。 Does anyone have any tips that I can try to help fix this?有没有人有任何提示我可以尝试帮助解决这个问题? Thanks谢谢

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

Extension to R Sahu 's answer :扩展R Sahu回答

The reason you cannot iterate using your original loop is because std::list does not offer an index operator (you would need to use std::vector instead).您不能使用原始循环进行迭代的原因是std::list不提供索引运算符(您需要改用std::vector )。

Alternative approach to the range based for loop (which I'd prefer, though, unless you have specific reasons not to do so) – or the way to go if you have no C++11 available – is using iterators:基于范围的 for 循环的替代方法(不过,我更喜欢,除非你有特定的理由不这样做)——或者如果你没有 C++11 可用的方法——是使用迭代器:

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

With C++11, you can have for(auto i = files.begin(); ... .使用 C++11,你可以有for(auto i = files.begin(); ...

Use cases for using iterator loop even with C++11 can be comparing items with their successors:即使使用 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
    }
}

There is already std::remove_if for and you should prefer it (together with a lambda; but don't forget to apply erase afterwards, see erase-remove-idiom !), so just for illustration;已经有std::remove_if for 并且您应该更喜欢它(与 lambda 一起使用;但不要忘记之后应用erase ,请参阅erase-remove-idiom !),因此仅用于说明; starting with the simpler approach:从更简单的方法开始:

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

Improved variant (which is what std::remove_if does as well):改进的变体(这也是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());

A minimal problem might remain with move or copy assignment operators not handling self-assignment correctly, which would be covered by if(!condition && i != pos) .移动或复制赋值运算符未正确处理自赋值可能仍然存在一个最小问题,这将被if(!condition && i != pos)覆盖。

If you are able to use C++11 or higher, you can use a range for loop to iterate over the contents of the list.如果您能够使用 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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM