std :: map具有不同的值数据类型

时间:2017-11-21 03:48:26

标签: c++ dictionary stdmap

我一直在搜索论坛和谷歌,并且很难理解我如何做我想做的事。

我的示例基于您在选举中看到的典型数据集。我想拆分一个分隔的字符串并创建一个地图以便以后访问 字符串看起来像这样: “名称= candidate1;表决= 1000;百分比= 10.5”

我可以按如下方式创建字符串映射

    while (getline(oss, key, '=') && getline(oss, value))
    {

      mCanData.insert(std::pair<std::string, std::string>(key, value));

    }

我想做什么,我不知道这是否可行,是在地图中插入具有不同数据类型的值(iekey =“name”value =“candidate1”,key =“vote”value = 1000,key =“percent”value = 10.5)。我想要创建的地图将设置一个私有类变量,稍后可以通过其他类的getter访问该变量。我无法使用升级库,所以请不要这样做。

任何帮助都会很棒,因为我现在迷路了。如果有更好的方法可以解决这个问题,我也想知道。

4 个答案:

答案 0 :(得分:3)

在C ++ std::map中,所有值都具有相同的类型。

通常,当您拥有类似这样的结构化数据时,您需要定义结构化类型:

class Vote {
  public:
    std::string name;
    int         vote;
    double      percent;
};

答案 1 :(得分:2)

如果您真的想在地图中放置非结构化数据,可以使用std::variant来执行此操作,然后访问以获取数据。<登记/> 它遵循一个最小的工作示例:

#include <variant>
#include <string>
#include <map>
#include <iostream>

int main() {
    std::map<std::string, std::variant<std::string, int, double>> mm;
    mm["name"] = "candidate1";
    mm["vote"] = 1000;
    mm["percent"] = 10.5;

    auto visitor = [](auto data){ std::cout << data << std::endl; };
    std::visit(visitor, mm["name"]);
    std::visit(visitor, mm["vote"]);
    std::visit(visitor, mm["percent"]);
}

wandbox上查看并运行。
如果它适用于你,主要取决于你可以使用或不使用C ++ 17的事实。你没有指定它,所以很难说。

话虽这么说,结构化数据(as suggested by @rici)似乎是一个更好的解决问题的方法 但是,我们既不能说出真正的问题是什么,也不能说出你设计其余代码的方式,所以值得提及的还有std::variant

答案 2 :(得分:0)

正如Rici上面提到的,正确的方法应该是拥有用户定义的类型,例如类或结构,并将其用作键。在您的情况下,您甚至可以使用set而不是map。请记得提供您的比较器功能或&lt;用户定义类型的运算符。因此,您的设计将如下所示。

struct Vote {
    std::string name;
    int         vote;
    double      percent;
};

struct myComparator
{
    bool operator() (const Vote& obj1, const Vote& obj2)
    {
      // Write your comparison logic which will be used by your container while inserting the data
    }
};

int main()
{
    std::set<Vote, myComparator> mySet;
    // Do your insertion and other operations.
    return 0;
}

答案 3 :(得分:0)

尝试使用没有C ++版本的依赖:

#include <iostream>
#include <map>
#include <cstdlib>


class Vote {
public:
    enum DATA_TYPE
    {
        STRING,
        INT,
        DOUBLE
    };
    Vote(int value)
        : m_type(DATA_TYPE::INT), m_ptr(new int(value)){}
    Vote(std::string& value)
        : m_type(DATA_TYPE::STRING), m_ptr(new std::string(value)){}
    Vote(double value)
        : m_type(DATA_TYPE::DOUBLE), m_ptr(new double(value)){}
    int toInt() {
        switch (m_type) {
        case DATA_TYPE::INT:
            return *(static_cast<int*>(m_ptr));
            break;
        case DATA_TYPE::DOUBLE:
            return (int)*(static_cast<double*>(m_ptr));
            break;
        case DATA_TYPE::STRING:
            return string2int(*(static_cast<std::string*>(m_ptr)));
        }
    }
    double toDouble() {
        switch (m_type) {
        case DATA_TYPE::INT:
            return (double)*(static_cast<int*>(m_ptr));
            break;
        case DATA_TYPE::DOUBLE:
            return *(static_cast<double*>(m_ptr));
            break;
        case DATA_TYPE::STRING:
            return string2double(*(static_cast<std::string*>(m_ptr)));
        }
    }
    std::string toString() {
        switch (m_type) {
        case DATA_TYPE::INT:
            return int2string(*(static_cast<int*>(m_ptr)));
            break;
        case DATA_TYPE::DOUBLE:
            return double2string(*(static_cast<double*>(m_ptr)));
            break;
        case DATA_TYPE::STRING:
            return *(static_cast<std::string*>(m_ptr));
        }
    }
    int string2int(std::string str)
    {
        return atoi(str.c_str());
    }
    double string2double(std::string str)
    {
        return atof(str.c_str());
    }
    std::string int2string(int value)
    {
        char buffer[10];
        itoa(value, buffer, 10);
        return std::string(buffer);
    }
    std::string double2string(double value)
    {
        char buffer[24];
        sprintf(buffer,"%f", value);
        return std::string(buffer);
    }
    DATA_TYPE type()
    {
        return m_type;
    }
private:
    std::string m_strValue;
    int m_intValue;
    double m_douValue;
    DATA_TYPE m_type;
    void *m_ptr;
};

int main()
{

    std::map<std::string, Vote> map;
    map.insert(std::pair<std::string, Vote>("Data1", 2));
    map.insert(std::pair<std::string, Vote>("Data2", 2.2));
    std::string Data3Value("1.31232");
    map.insert(std::pair<std::string, Vote>("Data3", Data3Value));

    for (std::map<std::string, Vote>::iterator it_map = map.begin();
         it_map != map.end();
         it_map ++) {
        Vote::DATA_TYPE type = (*it_map).second.type();
        switch (type) {
        case Vote::DATA_TYPE::INT:
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toInt() << std::endl;
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toDouble() << std::endl;
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toString() << std::endl;
            break;
        case Vote::DATA_TYPE::DOUBLE:
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toInt() << std::endl;
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toDouble() << std::endl;
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toString() << std::endl;
            break;
        case Vote::DATA_TYPE::STRING:
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toInt() << std::endl;
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toDouble() << std::endl;
            std::cout << "Key: " << (*it_map).first << ", value: " << (*it_map).second.toString() << std::endl;
            break;
        }

    }
    return 0;
}

你可以提供3种类型的构造函数然后你可以接受3种类型来构造对象,然后提供一个void指针,指向构造对象时我们“new”的数据。当我们调用toInt(),toDouble(),toString()函数并使用static_cast将指针强制转换为我们想要的数据类型。