Adding pair in set - c++

I am trying to insert pair of int and string in my set. What i am trying to do is implement a hash map using sets, I am storing the number and its corresponding string using store function and then retrieving the string using retrieve. Please suggest what is the problem and is there any way it can be done more efficiently. The error is in store function. I have not written main function as its just taking input and calling the functions.
typedef pair<int, string> pairs;
pairs p;
set<pairs> s;
set<pairs>::iterator it;
int i=0;
void store(int num,string s)
{
p[i].first=num; //error is while I am using the pair to store the string
p[i].second=s;
s.insert(p[i]);
i++;
}
string retrieve(int num)
{
for(it=s.begin();it!=s.end();++it)
{
pairs m = *it;
if(m.first==num)
{
return m.second;
}
}
}
My error:
error: no match for ‘operator[]’ (operand types are ‘pairs {aka std::pair<int, std::basic_string<char> >}’ and ‘int’)
p[i].first=num;

pairs is a type alias for pair<int, string>. std::pair does not have an operator[] overload.
Assuming you want pairs to represent a collection of pairs, you need to make your pairs a container (e.g. a vector or an array).
As Martin Bonner noted in the comment, the symbol s inside store refers to the string s parameter. Change it to avoid clashing with set s's identifier.
typedef pair<int, string> pairs[100];
pairs p;
void store(int num, string str)
{
p[i].first=num;
p[i].second=str;
s.insert(p[i]);
i++;
}

Related

why would i have compile error when i'm using a STL map?

I'm using a variable A of type map<string, int> and a string s in my program below:
map<string, int> A;
A["X"] = 10;
string s = "LXX";
int ans += A[s[2]];
but when i run the code, compile error comes:
no match for 'operator[]' (operand types are 'std::map<std::__cxx11::basic_string<char>, int>' and '__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type {aka char}')
a char in string like s[2] cannot be an index of a map? How should i use it correctly to get that(A[s[2]])?
If you use [] operator on string, you are getting an char right?
Key of your map is std::string while you are passing an char which arent compatible.
What you have to do is pass an valid key -> std::string to get mapped int.
map<string, int> m;
std::string s("test");
m[s] = 10;
if ( m.find(s) == m.end() )
{
// not found
} else
{
// found
}
If you would like to map characters of your std::string you have to change declaration of your map to std::map<char, int> or pass an strings with 2 characters. (one is null terminating character)
A[std::string(s[i])] ---> 'c' to "c\0"
If you are mapping characters from the string to an int, try changing the map<string, int> to map<char, int>. If you are mapping string to int, try accessing with A[s].

Constructing a Map With Vectors as Values

I am trying to construct a map that maps a string to a vector of unsigned integers. The way that I construct this map is as follows:
void PixelP1ROCDACSettings::getDACs(map<string,vector<unsigned int>>& dacs) const
{
dacs.clear();
dacs.insert(pair<string, vector<unsigned int> > (k_DACName_Vdd, make_vector(Vdd_, k_DACAddress_Vdd)));
dacs.insert(pair<string, vector<unsigned int> > (k_DACName_Vana,make_vector(Vana_, k_DACAddress_Vana)));
...
}
Where make_vector is defined as follows:
std::vector<unsigned int> make_vector(unsigned int DACValue,
unsigned int DACAddress) const ;
My questions are:
1) I would like to get access each individual value in my vector, I've tried to do,
dacs[key][index] but that didn't seem to work. Is there a special syntax to do this?
2) Additionally, I would like to iterate across my map, How would I do that?
Thanks in advance.
If you are using c++11 you can iterate with
for (auto& keyvaluepair : dacs) {
//keyvaluepair.first is your string
//keyvaluepair.second is your vector
}
also dacs[key][index] is the correct way to access the indexth element in the vector mapped to by key.

How to sort C++ map keys with std::greater?

I'm creating a std::map<int, int> in C++ that I'd prefer to have they keys sorted from highest to lowest instead of the default sort order. My research lead me to std::greater which looked promising but when trying to use it I'm getting a compile error:
invalid type argument of unary ‘*’ (have ‘int’)
My map declaration is:
std::map<int, int, std::greater<int> > numMap;
And the error is getting thrown from this function:
void Row::addNumber(int num, int pos) {
numMap.insert(num, pos);
}
Answers to similar questions such as this include parenthesis in the declaration, i.e. std::greater() - but when I include those I get multiple errors regarding a function returning a function.
The problem – call of std::map::insert member function with invalid parameters: there are two integer values provided; but there must be std::pair<int, int>. Please see the reference: std::map::insert.
Preferable option
For convenience (just not to repeat the map type parameters), create a typedef for the map:
typedef std::map<int, int> IntMap;
The std::map has type definition for std::pair (pair representation) – std::map::value_type.
So, for example, if there is a std::map<int, int> the std::map::value_type would be std::pair<int, int>.
Use the std::map::value_type constructor (IntMap::value_type in this case):
class Row {
public:
void Row::addNumber(int num, int pos)
{
m_numMap.insert(IntMap::value_type(num, pos));
}
private:
typedef std::map<int, int> IntMap;
IntMap m_numMap;
};
Alternatives:
Use std::make_pair() function:
#include <utility>
...
void Row::addNumber(int num, int pos)
{
numMap.insert(std::make_pair(num, pos));
}
Directly use std::pair constructor:
void Row::addNumber(int num, int pos)
{
numMap.insert(std::pair<int, int>(num, pos));
}
A bit more pedantic than Sergey's answer (which also definitely works), instead Use:
typedef std::map<int, int, std::greater<int> > MyMap;
MyMap numMap;
void Row::addNumber(int num, int pos)
{
numMap.insert(MyMap::value_type(num, pos));
}
The benefit being that if you change the type of the map, you have less code to change later. And much less likely but still possible, if the implementation of std::map changes its value_type from std::pair to something else (in a future version of the stl), you are impervious to that change.

Search in vector<std::pair<int, vector<int> > >

I would like to search within a vector<std::pair<int, vector<int> > >. This won't work due to the vector parameters:
std::vector<std::pair<int, std::vector<int> > > myVec;
iterator = find(myVec.begin(), myVec.end(), i);
Search would be on the first std::pair template parameter (int), in order to get the vector associated with it.
std::vector<std::pair<int, std::vector<int> > > myVec;
This requires C++0x for the lambda expression:
typedef std::pair<int, std::vector<int>> pair_type
std::find_if(myVec.begin(), myVec.end(), [i](pair_type const& pair)
{ return pair.first == i; });
If you're not using C++0x then either roll out your own loop or use something like Boost.Phoenix/Boost.Lambda.
Or, for both cases, why not use std::map?
You could make do with the following (pretty ugly) functoid:
struct FindFirst {
FindFirst(int i) : toFind(i) { }
int toFind;
bool operator()
( const std::pair<int, std::vector<int> > &p ) {
return p.first==toFind;
}
};
using it like this ( I couldn't get bind2nd to work - that's why I used the c'tor ):
int valueToFind = 4;
std::find_if(myVec.begin(), myVec.end(), FindFirst(valueToFind));
I think what you would like is a map:
std::map< int, vector< int > > foo;
You can then add elements, search by key etc:
int key = 4; //This will be the key
vector<int> value(5, 4); //Fill some values (5 4's in this case) into the vector
foo[key]=value; //Adds the pair to the map. Alternatively;
foo.insert( make_pair(key, value) ); //Does the same thing (in this context)
Looking at the way you've done things though, you might be wanting a std::multimap (which allows multiple values to have the same key) Class docs here
You're trying to map an int to a vector of int.
So try map<int, vector<int> >.
The second template parameter of a vector is the allocator - your compiler can probably puzzle out what you wanted to say, the declaration is wrong anyway. What you probably want is some sort of map type, like iammilind suggested.

How to use STL unsorted key-value as pair in map

I need to use STL C++ map to store key value pairs.
I need to store more than one data information in stl map.
e.g
Need to store DataType,Data and its behavior as(in param/outparam) all in string format.
But map always use key value pair
so if I
store it like
std::map<map<"int","50",>"behavior">.
But always it sorts the the data on basis of keys which I dont want. If I use like ..
pair<string, pair<string,string> >;
pair<string, pair<string,string>>("int",("100","in"));
This prompts compile time error!
error C2664: 'std::pair<_Ty1,_Ty2>::pair(const std::pair<_Ty1,_Ty2> &)' : cannot convert parameter 1 from 'const char *' to 'const std::pair<_Ty1,_Ty2> &'
What should be the exact solution of the above problem?
Regards
If you don't want ordering, don't use ordered containers like map or set. You could achieve what you're looking for using a class and a vector. The sorted nature of std::map is what makes it efficient to lookup by key. If you want/need unsorted and more hash like behavior for lookups, look at Boost unordered containers. Note that this doesn't guarantee the order in is going to be the order out. I'm assuming you want to preserve the order of the types your putting in the container, the example below will do that.
#include <iostream>
#include <vector>
using namespace std;
class DataBehavior
{
public:
DataBehavior(const string &type,
const string &data,
const string &behavior)
:type(type), data(data), behavior(behavior)
{
}
const string &getType() const { return type; }
const string &getData() const { return data; }
const string &getBehavior() const { return behavior; }
private:
string type;
string data;
string behavior;
};
typedef vector<DataBehavior> Ctr;
int main (int argc, char *argv[])
{
Ctr ctr;
ctr.push_back(DataBehavior("int", "50", "behavior"));
ctr.push_back(DataBehavior("int", "80", "behavior"));
ctr.push_back(DataBehavior("string", "25", "behavior2"));
for (Ctr::const_iterator it = ctr.begin(); it != ctr.end(); ++it)
{
cout << "Type: " << it->getType() << " "
<< "Data: " << it->getData() << " "
<< "Behavior: " << it->getBehavior() << "\n";
}
return 1;
}
You're declaring the variables wrong in the
pair<string, pair<string,string> >;
pair<string, pair<string,string>>("int",("100","in"));
You'd need to do
pair<string, pair<string,string>>("int",pair<string,string>("100","in"));
which is fairly verbose. You could use the make_pair function to significantly shorten that:
make_pair( "int", make_pair( "100", "in" ) );
Also, as the others have said, if you don't want sorted order, use unordered_map from TR1 or Boost. If you're on MS you can use hash_map instead.
Need to store DataType,Data and its
behavior as(in param/outparam) all in
string format. But map always use key
value pair
To me it seems you need to use different data structure, e.g.
typedef std::tuple<std::string, // DataType
std::string, // Data
std::string> element_type; // behaviour
// use can replace tuple with sth like:
//struct element_type {
// std::string m_DataType;
// std::string m_Data;
// std::string m_Behaviour;
// ... ctors, operators ...
//};
// or even with std::array<std::string, 3>
std::set<element_type> elements_set;
// or
typedef int32_t element_id;
std::map<element_id, element_type> elements_map;
And you've got rather a design problem than a programming one.
Why do you use a map in the first place? What do you want to use as lookup key -- the datatype? The value? The "param/outparam" characteristic?
Whatever you want to use as a key should go first, and the rest could be a struct / pointer / string (*urg*) / ... .
So I suggest you give some more thought to your needs and design a datastructure accordingly.