我一直在搜索论坛和谷歌,并且很难理解我如何做我想做的事。
我的示例基于您在选举中看到的典型数据集。我想拆分一个分隔的字符串并创建一个地图以便以后访问 字符串看起来像这样: “名称= 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访问该变量。我无法使用升级库,所以请不要这样做。
任何帮助都会很棒,因为我现在迷路了。如果有更好的方法可以解决这个问题,我也想知道。
答案 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将指针强制转换为我们想要的数据类型。