【问题标题】:Iterate through a vector of objects and find a variable that matches one pulled from a text file遍历对象向量并找到与从文本文件中提取的变量匹配的变量
【发布时间】:2018-08-21 18:49:51
【问题描述】:

所以我有一个对象向量

vector<Module*> moduleVector;         

我需要遍历它并将对象的属性与我从文本文件中提取的另一个属性进行比较

我使用ifstreamgetLine()来存储需要与对象属性进行比较的元素(fileD是打开的文件,markModId是字符串变量)

getline(fileD, markModId, ' ');

但我不确定如何在迭代器中引用对象的属性。所以我的问题是,

如何使用迭代器将文件中的属性与对象进行比较?

这里是我的对象构造函数供参考(id是我要比较的属性)

Module::Module(string id, string title, string lecturer, int 
courseworkWeight)
{
   code = id;
   name = title;
   lect = lecturer;
   cwWeight = courseworkWeight;
   exMark = 0; //ex mark initialised as 0
   /*
   Map to store coursework marks
   */
   map<string, float> CWmarks;
   //cwMarks.clear(); //cw marks map cleared
   //create a map that stores
}

exMark是需要添加到对象的属性。 Module 构造函数中的所有属性都是private

【问题讨论】:

    标签: c++ algorithm c++11 iterator stdvector


    【解决方案1】:

    如何使用 迭代器?

    简答:假设您有一个迭代器std::vector&lt;Module*&gt;::iterator iter,您可以访问Module 类的公共成员,例如:

    (*iter)->/*public member*/;
    

    长答案:首先,您需要一个用于私人成员id 的getter 和一个用于exMark 的setter,通过它您可以获得每个Moduleid 和与文件中的 id 进行比较,然后将其 exMark 设置为某个值。

    std::string getId()const { return code; }
    void setExMark(const double newMark) { exMark = newMark; }
    

    如果要更改Module 的第一个真实实例,可以使用std::find_if 查找Module

    std::string idFromFile = "two";
    auto Condition = [&idFromFile](Module* element){ return element->getId() == idFromFile; };
    auto iter = std::find_if(moduleVector.begin(), moduleVector.end(), Condition);
    
    if(iter != moduleVector.end())
         (*iter)->setExMark(10.0);  // see this
       // ^^^^^^^^^
    

    See a sample code here

    对于多个实例,您可以这样做:

    for(auto iter = moduleVector.begin(); iter != moduleVector.end(); ++iter)
          if ( (*iter)->getId() == idFromFile)
             (*iter)->setExMark(10.0);
    

    注意:在现代 C++ 中,您可以使用 smart pointers,而不是原始指针,这将在对象超出范围时自动删除。

    【讨论】:

    • 您假设codeexMark 是私有的,而不是一开始就公开的。 OP 没有显示 Module 的声明
    • @JeJo 我实现了 getter 和 setter,但由于某种原因 exMark 仍然显示为零。
    • @Sean 你检查了输出:this:ideone.com/d2lpDB 吗?但是,如果要更改 id 的所有匹配项,您需要遍历向量并设置 exMark。像这样的东西:ideone.com/O3xaWb
    • @JeJo 嗨 Jejo,我检查并尝试了两种方法,但仍然输出 exMark 为 0
    • @Shaun 它应该可以工作。我认为问题出在与Module 的成员变量进行比较的文件中的字符串或变量上。尝试调试(或打印文件的输出数据)代码并查看您从文件中获得的值是什么。 (我假设成员变量没问题)
    【解决方案2】:

    只需取消对迭代器的引用以访问其Module* 指针,然后您可以使用operator-&gt; 访问对象,例如:

    for (std::vector<Module*>::iterator iter = moduleVector.begin(), end = moduleVector.end(); iter != end; ++iter)
    {
        Module *m = *iter;
        if (m->code == markModId)
            m->exMark = ...;
    }
    

    或者,如果您使用 C++11 或更高版本,让编译器为您处理迭代器:

    for (Module *m : moduleVector)
    {
        if (m->code == markModId)
            m->exMark = ...;
    }
    

    或者,使用带有标准迭代算法之一的 lambda,例如:

    std::for_each(moduleVector.begin(), moduleVector.end(),
        [&](Module *m)
        {
            if (m->code == markModId)
                m->exMark = ...;
        }
    );
    

    如果您只对更新 1 个模块感兴趣,则在找到所需模块时中断循环:

    for (std::vector<Module*>::iterator iter = moduleVector.begin(), end = moduleVector.end(); iter != end; ++iter)
    {
        Module *m = *iter;
        if (m->code == markModId)
        {
            m->exMark = ...;
            break; // <-- add this
        }
    }
    

    for (Module *m : moduleVector)
    {
        if (m->code == markModId)
        {
            m->exMark = ...;
            break; // <-- add this
        }
    }
    

    auto iter = std::find_if(moduleVector.begin(), moduleVector.end(),
        [&](Module *m) { return (m->code == markModId); });
    if (iter != moduleVector.end())
    {
        Module *m = *iter;
        m->exMark = ...;
    }
    

    【讨论】:

      猜你喜欢
      • 2019-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多