【问题标题】:Iterating over a list of objects c++遍历对象列表c ++
【发布时间】:2019-02-11 06:30:29
【问题描述】:

基本上我正在为一个类项目创建一个基本的 shell 程序。我一直在遍历目录中的文件/文件夹。

我的错误在于函数 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); 
};

【问题讨论】:

  • 您设计中的地图看起来已经过时了 - 而不是只有一个条目的地图,只有两个简单的列表成员。
  • 我没有看到 Folder 的任何定义 - 你是否打算改为 std::list&lt;Directory&gt;(至少有意义......)?
  • 所以,我使用地图的原因是因为我要制作它,以便您可以添加更多目录、文件和文件夹。我应该继续使用它还是切换到简单的列表成员?
  • 是的,我只是在测试以确保它在进入文件夹类之前可以与文件一起使用
  • 您已经可以将任意数量的文件或文件夹添加到列表中。如果要为多个不同的目录路径添加条目,则映射 only 是有意义的。 DirectoryFolder 将为同一事物获得两个不同的类。没有什么反对将其他 Directory 实例添加到父 Directory 实例。这不是也能更好地反映文件系统吗?

标签: c++ list class object listiterator


【解决方案1】:

扩展至R Sahuanswer

您无法使用原始循环进行迭代的原因是std::list 不提供索引运算符(您需要改用std::vector)。

基于范围的 for 循环的替代方法(不过,我更喜欢这种方法,除非你有特定的理由不这样做)——或者如果你没有可用的 C++11 的话——使用迭代器:

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 了,你应该更喜欢它(连同一个 lambda;但不要忘记应用 erase 之后,请参阅 erase-remove-idiom!),所以只是为了说明;从更简单的方法开始:

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 &amp;&amp; i != pos) 将涵盖该问题。

【讨论】:

    【解决方案2】:

    如果您能够使用 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();
        }
    }
    

    【讨论】:

    • 太棒了!是的,我可以使用它,这很有效!感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    • 2018-05-08
    • 2015-03-17
    • 2011-06-11
    • 1970-01-01
    • 2023-03-04
    • 2016-12-29
    相关资源
    最近更新 更多