does map key have an address that I can point to? - c++

Can I treat map key as pointer?
I have a struct which member is vector of strings, and I have a map
Is it possible to fill my vector with pointers to string1 ?
example
struct A
{
vector<string> v;
}
map<string, string> m;
m["hello"] = "test";
m["world"] = "test2";
A test;
for(map<string, string>::iterator it = m.begin(); it != m.end(); it++)
test.v.push_back(it->first)
can I do this?

does map key have an address that I can point to?
Yes, like all objects it has an address.
Can I treat map key as pointer?
No, it's not a pointer. But you can take its address.
Is it possible to fill my vector with pointers to string1 ?
No, because it's a vector of strings, not pointers; so you can fill it with copies of the map keys (as your code does), but not pointers. You could have a vector of pointers:
vector<string const *> v;
and fill that with pointers to the map keys:
test.v.push_back(&it->first);
If you remove any keys from the map, then make sure you don't try to use that pointer afterwards.

In a way, yes.
If you have a key stored somewhere, or read as input, then you can use it to search the map to see if if the key exists and get its value.

Related

store objects in vector, which is inside a map in C++

I am trying to create a map that contains a string key and an vector of myClass.
std::map<string,vector<myClass>> m;
I need to populate the vector as well and the map dynamically (reading values from a file).
class myClass{
string dataMember1;
...
myClass()
{ ... }
};
How should i proceed with it??
Also i want to be able to access the objects in the vector based on the string key.
for example:
std::map<string,vConnect>::iterator pos;
pos = mapGraph.find(string);
cout<<(pos->second)[0]->DataMemberofmyClass
will (pos->second)[0] indicate the first myClass object stored in the vector??
Thanks
Generally, when the mapped type is a container, just using []
everywhere works well; if the entry isn't present, it will be
created with an empty container, so things like:
m[key].push_back( newElement );
or
m[key].begin(), m[key].end()
or even:
if ( !m[key].empty() )
doSomethingWith( m[key].second[0] );
work correctly. If you're doing a number of operations on the
same element (as in the last two cases), you might want to hold
it in a reference:
std::vector<MyClass>& elem = m[key];
// ...
About the only exception would be if you're not modifying the
element, and you don't want to create the entry if it is empty.
In those cases, you'll need find, and a test:
std::map<std::string, std::vector<MyClass>>::const_iterator
entry = m.find( key );
if ( entry != m.end() ) {
std::vector<MyClass>& elem = entry->second;
// ...
}
Working with such nested types is not much different from working with simple map or vector. So an element of the map is a vector. Get this element and use it as a vector.
pos = mapGraph.find(string);
Returns an iterator in the map.
(pos->second)
Is the vector that is the value at this iterator. So simply use it as you would use a vector. Your code is correct apart from the fact you never check if an element was indeed found.
std::map<string,vConnect>::iterator pos;
pos = mapGraph.find(string);
if (pos != mapGraph.end()) {
cout<<(pos->second)[0].DataMemberofmyClass
}
EDIT(Thanks to us2012): in fact you had a small mistake (pos->second)[0] is an Object of MyClass so you access its members using . not using ->.

Iterator over Vector class (array)

These iterator in the collection classes confuses me. I got a Map with key of string, and value being a Vector class (similar to an array). As i understand it my iterator variable it is assigned to the map. So i should be able to to get it´s value and assign it to a new Vector class so I can read it´s contents or know it´s size etc... but how do I do this?
for (Map<string, Vector<string> > :: iterator it = array0.begin();
it != array0.end(); it++)
{
Vector<string> arr = it; // Error
Assuming your Map is a std::map, the elements of a map are pairs of (key,value), so the value is the second element of the pair:
Vector<string> arr = it->second;

How can I access a specific element in a std::map with more than 2 elements?

I am trying to access a specific element out of a std::map with more than two elements. Here is an example:
std::map <int, CString, CString, CString> map;
//Initialise
map[0] = _T("stuff1"), _T("stuff2"), _T("stuff3");
//now if I just want to access stuff3 is it this:
CString str = map[0][2];
//or something more like this?
CString str = map[0]. ???
Any help would be great thanks.
edit: Thanks sorry about that, first time using maps, I was wondering why I couldn't find any information on std::map 's with more elements inside.
Have you tried to compile this? It shouldn't.
You can create only a map with exactly 1 key and 1 value for each element.
But the value can be compound, so you can write
struct ValueType {
CString v1;
CString v2;
CString v3;
}
std::map <int, ValueType> map;
and access elements like map[somekey].v3;
To insert a value in such a map, you'll have to write
ValueType strings = {"1","2","3"};
map.insert(999, strings);
Or you may create a helper function (i.e. void addToMap(std::map <int, ValueType> &map, CSting const& v1, CString const& v2, CString const& v3) ), which will fill your map in a more convenient way.
std::map <int, CString, CString, CString> map; is illegal.
Either use a std::multimap or a std::map<int,std::vector<CString> >.
I believe this what you are looking for
std::map <int, std::list<CString> > myMap;
then you'll access myMap[0], then access each element in the returned std::list<CString>

C++ map<string, vector<char> > access

I've created a map of vectors that looks like this:
map<string, vector<char> > myMap;
string key = "myKey";
vector<char> myVector;
myMap[key] = myVector;
I want to be able to append 'char's' to the vector in the map but I can't figure out how to access said vector to append once the particular key/value(vector) has been created. Any suggestions? I'm iterating over char's and might be adding a lot to the vector as I go so it would be nice to have a simple way to do it. Thanks.
I would like the vector in map to be appended as I go. I don't need the original vector...I just need to return the map of key/vector's that I've created (after apending) so that I can pass it to another function. What does the * in map* > do? Is that refrencing a pointer? (I haven't gotten there in lecture yet) Also, do I need:
myMap[key]->push_back('s');
or
myMap[key].push_back('s');
??
To append:
myMap[key].push_back('c');
Or use myMap.find, but then you have to check whether you get an end iterator. operator[] returns a reference to the vector.
But this modifies the vector stored in the map, not the original one, since you've stored a copy in the map with myMap[key] = myVector;. If that's not what you want, you should rethink your design and maybe store (smart) pointers to vectors in your map.
Given you know the key:
string key = "something";
char ch = 'a'; // the character you want to append
map<string, vector<char> >::iterator itr = myMap.find(key);
if(itr != myMap.end())
{
vector<char> &v = itr->second;
v.push_back(ch);
}
you could also use the map::operator[] to access the map entry, but if the key does not exist, a new entry with that key will be created:
vector<char> &v = myMap[key]; // a map entry will be created if key does not exist
v.push_back(ch);
or simply:
myMap[key].push_back(ch);
To access the mapped value, which in your case is a vector, you just supply the key in square brackets like you did to assign the value.
So, to append 'a':
myMap[key].push_back('a');
I have an new suggestion. You can use vector<char>* instead of vector<char> in order to collect pointer of vectors in your map. For more information see the bellow code:
map<string, vector<char>* > myMap;
string key = "myKey";
vector<char>* myVector = new vector<char>();
myMap[key] = myVector;
myMap[key]->push_back('S');

std::map keys in C++

I have a requirement to create two different maps in C++. The Key is of type CHAR* and the Value is a pointer to a struct. I am filling 2 maps with these pairs, in separate iterations. After creating both maps I need find all such instances in which the value of the string referenced by the CHAR* are same.
For this I am using the following code :
typedef struct _STRUCTTYPE
{
..
} STRUCTTYPE, *PSTRUCTTYPE;
typedef pair <CHAR *,PSTRUCTTYPE> kvpair;
..
CHAR *xyz;
PSTRUCTTYPE abc;
// after filling the information;
Map.insert (kvpair(xyz,abc));
// the above is repeated x times for the first map, and y times for the second map.
// after both are filled out;
std::map<CHAR *, PSTRUCTTYPE>::iterator Iter,findIter;
for (Iter=iteratedMap->begin();Iter!=iteratedMap->end();mapIterator++)
{
char *key = Iter->first;
printf("%s\n",key);
findIter=otherMap->find(key);
//printf("%u",findIter->second);
if (findIter!=otherMap->end())
{
printf("Match!\n");
}
}
The above code does not show any match, although the list of keys in both maps show obvious matches. My understanding is that the equals operator for CHAR * just equates the memory address of the pointers.
My question is, what should i do to alter the equals operator for this type of key or could I use a different datatype for the string?
My understanding is that the equals operator for CHAR* just equates the memory address of the pointers.
Your understanding is correct.
The easiest thing to do would be to use std::string as the key. That way you get comparisons for the actual string value working without much effort:
std::map<std::string, PSTRUCTTYPE> m;
PSTRUCTTYPE s = bar();
m.insert(std::make_pair("foo", s));
if(m.find("foo") != m.end()) {
// works now
}
Note that you might leak memory for your structs if you don't always delete them manually. If you can't store by value, consider using smart pointers instead.
Depending on your usecase, you don't have to neccessarily store pointers to the structs:
std::map<std::string, STRUCTTYPE> m;
m.insert(std::make_pair("foo", STRUCTTYPE(whatever)));
A final note: typedefing structs the way you are doing it is a C-ism, in C++ the following is sufficient:
typedef struct STRUCTTYPE {
// ...
} *PSTRUCTTYPE;
If you use std::string instead of char * there are more convenient comparison functions you can use. Also, instead of writing your own key matching code, you can use the STL set_intersection algorithm (see here for more details) to find the shared elements in two sorted containers (std::map is of course sorted). Here is an example
typedef map<std::string, STRUCTTYPE *> ExampleMap;
ExampleMap inputMap1, inputMap2, matchedMap;
// Insert elements to input maps
inputMap1.insert(...);
// Put common elements of inputMap1 and inputMap2 into matchedMap
std::set_intersection(inputMap1.begin(), inputMap1.end(), inputMap2.begin(), inputMap2.end(), matchedMap.begin());
for(ExampleMap::iterator iter = matchedMap.begin(); iter != matchedMap.end(); ++iter)
{
// Do things with matched elements
std::cout << iter->first << endl;
}