在std :: vector中查找Iterator

时间:2017-10-25 21:54:25

标签: c++ c++11 vector iterator

我遇到了问题,我正在尝试创建一个系统来读取和写入.ini文件,但我仍然坚持如何正确添加部分/键。我以为我可以将它们作为对象添加到std :: vector中,所以我写了下面的代码片段(我删除了无关的代码):

// .h

class Ini
{
public:
    class IniSection
    {
        friend class Ini;

    private:
        IniSection(Ini *ini, std::string section);
        ~IniSection();

    private: 
        Ini *pIni;
        std::string sectionName;
    };

    vector<IniSection *>::iterator Ini::FindSection(std::string section);

    IniSection *AddSection(std::string name);

private:
    vector<IniSection *> Sections;
};

typedef Ini::IniSection IniSection;



// .cpp


IniSection::IniSection(Ini *ini, std::string section) : pIni(ini), sectionName(section)
{

}

vector<IniSection *>::iterator Ini::FindSection(std::string section)
{
    IniSection tempSection(NULL, section);

    return find(Sections.begin(), Sections.end(), tempSection); // ERROR
}

IniSection *Ini::AddSection(std::string name)
{
    vector<IniSection *>::const_iterator iter = FindSection(name);

    if (iter == Sections.end())
    {
        IniSection *newSection = new IniSection(this, name);
        Sections.push_back(newSection);
        return newSection;
    }
    else
        return *iter;
}

如你所见,我用

标记了一行
  

//错误

那是因为当我尝试构建它时,我收到了这个错误:

  

错误C2679二进制'==':找不到右侧的操作符   'const Ini :: IniSection'类型的操作数(或者没有可接受的   转化率)

它出现在算法库中。所以我想我尝试获取迭代器的方式是错误的,所以也许有人能够帮助我。我在互联网上找不到适合我的东西。提前谢谢!

2 个答案:

答案 0 :(得分:1)

您需要向班级IniSection添加IniSection,以回答“bool operator==(const IniSection& lhs, const IniSection& rhs) { return (lhs.sectionName == rhs.sectionName); } 等于2的实例”这一问题。像这样:

{{1}}

答案 1 :(得分:1)

上述代码存在一些问题。根据建议,您需要为operator ==定义IniSection,以便std::find能够比较Sections向量中的条目。但是,还有另一个问题:您的FindSection有点无用,因为您无法测试迭代器是否在Sections::end()返回了点,因为Sections是私有成员。如果我建议,您需要添加类似于返回hasSection的{​​{1}}方法,并使用该方法测试是否存在节。我冒昧地修改代码来说明这一点,随意根据你的需要改变它。

main.hpp

bool

的main.cpp

#ifndef MAIN_HPP
#define MAIN_HPP

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

class Ini
{
public:
    class IniSection
    {
        friend class Ini;

        Ini& pIni;
        std::string sectionName;
    public:
        IniSection(Ini& ini, const std::string& section);

        friend bool operator == (const IniSection& _this, const IniSection& _other)
        {
            return _this.sectionName == _other.sectionName;
        }
    };

    std::vector<IniSection>::iterator FindSection(const std::string& section);

    std::vector<IniSection>::iterator AddSection(const std::string& section);

    bool hasSection(const std::string& section);

    std::vector<std::string> sectionNames();

private:
    std::vector<IniSection> Sections;
};

typedef Ini::IniSection IniSection;


#endif // MAIN_HPP

打印:

#include "main.hpp"


IniSection::IniSection(Ini& ini, const std::string& section)
    :
      pIni(ini),
      sectionName(section)
{}

std::vector<IniSection>::iterator Ini::FindSection(const std::string& section)
{
    IniSection tempSection(*this, section);
    return std::find(Sections.begin(), Sections.end(), tempSection);
}

std::vector<IniSection>::iterator Ini::AddSection(const std::string& section)
{
    std::vector<IniSection>::iterator iter = FindSection(section);

    if (iter == Sections.end())
    {
        Sections.emplace_back(*this, section);
        return Sections.end() - 1;
    }
    else
    {
        return iter;
    }
}

bool Ini::hasSection(const std::string& section)
{
    return FindSection(section) != Sections.end();
}

std::vector<std::string> Ini::sectionNames()
{
    std::vector<std::string> names;
    for (const auto& s : Sections)
    {
        names.push_back(s.sectionName);
    }
    return names;
}

int main()
{
    Ini ini;

    ini.AddSection("Section1");
    ini.AddSection("Section2");
    ini.AddSection("Section3");

    if (ini.hasSection("Section1"))
    {
        std::cout << "Ini contains section 1!\n";
    }

    if (!ini.hasSection("Section4"))
    {
        std::cout << "Adding section 4...\n";
        ini.AddSection("Section4");
    }

    std::cout << "Ini contains the following sections:\n";
    for (const auto& s : ini.sectionNames())
    {
        std::cout << "\t" << s << "\n";
    }

    return 0;
}

另外,正如评论中所建议的那样,Ini contains section 1! Adding section 4... Ini contains the following sections: Section1 Section2 Section3 Section4 是一个很好的表演者,非常适合这种情况。

P.S。您可能已经注意到我用对象替换了原始指针。像std::unordered_map这样的STL容器在内部处理分配和释放,因此不需要使用原始指针。

编辑

我已经修改了pastebin中的代码,但是有些东西丢失了(我不确定std::vector是什么类型 - 也许是IniPath?)。还有很大的改进空间,例如,您可以向std::string添加几行,以便在不存在时自动添加一个部分(因此您不必检查是否存在{getSection 1}}首先)。如前所述,使用hasSection可以大大受益,因为插入,删除和查找都是分摊的常量时间。使用std::unordered_map,查找和检索元素将是线性时间。我不清楚的另一件事是你需要将一个引用(或原始代码中的指针)存储到父对象(例如std::vector内的IniSection&)。据我所知,你没有使用这些。只要不存储原始指针,您也不需要实现自己的析构函数。

免责声明:我没有编译和测试此代码。

P.S。您可能希望在CodeReview上发布此内容以进一步改进。

<强> main.hpp

IniKey

<强>的main.cpp

#include <vector>
#include <string>
#include <fstream>
#include <algorithm>

class Ini
{

public:

    Ini();
    ~Ini();

    bool Load(std::string path);

    void Load(std::istream& input);

    bool Save(std::string path);

    void Save(std::ostream& output);

    void Create(std::string path);

    class IniSection
    {
        friend class Ini;

        Ini& pIni;
        std::string sectionName;

    public:
        IniSection(Ini& ini, const std::string& section);
        ~IniSection();

        friend bool operator == (const IniSection& _this, const IniSection& _other)
        {
            return _this.sectionName == _other.sectionName;
        }


        std::string GetSectionName();

        class IniKey
        {
            friend class IniSection;

            IniSection& pSection;
            std::string keyName;
            std::string keyValue;
            std::string commentValue;

        public:
            IniKey(IniSection& section, const std::string& key);
            ~IniKey();

            friend bool operator == (const IniKey& _this, const IniKey& _other)
            {
                return _this.keyName == _other.keyName;
            }

            void SetValue(std::string value);

            std::string GetValue();

            std::string GetKeyName();

            void AddComment(std::string comment);

            std::string GetComment();
        };

        void RemoveAllKeys();

        std::vector<IniKey>::iterator FindKey(const std::string& key);

        std::vector<IniKey>::iterator AddKey(const std::string& key);

        std::vector<IniKey>::iterator GetKey(const std::string& key);

        bool hasKey(const std::string& key);

        std::string GetKeyValue(const std::string& key);

        void SetKeyValue(const std::string& key, const std::string& value);

    private:
        std::vector<IniKey> Keys;
    };

    void RemoveAllSections();

    std::vector<IniSection>::iterator FindSection(const std::string& section);

    std::vector<IniSection>::iterator AddSection(const std::string& section);

    std::vector<IniSection>::iterator GetSection(const std::string& section);

    bool hasSection(const std::string& section);

    std::string GetKeyValue(std::string section, std::string key);

    void SetKeyValue(std::string section, std::string key, std::string value);

private:
    std::vector<IniSection> Sections;
};

typedef Ini::IniSection IniSection;
typedef IniSection::IniKey IniKey;