How can I print out C++ map values? - c++

I have a map like this:
map<string, pair<string, string>> myMap;
And I've inserted some data into my map using:
myMap.insert(make_pair(first_name, make_pair(middle_name, last_name)));
How can I now print out all the data in my map?

for(map<string, pair<string,string> >::const_iterator it = myMap.begin();
it != myMap.end(); ++it)
{
std::cout << it->first << " " << it->second.first << " " << it->second.second << "\n";
}
In C++11, you don't need to spell out map<string, pair<string,string> >::const_iterator. You can use auto
for(auto it = myMap.cbegin(); it != myMap.cend(); ++it)
{
std::cout << it->first << " " << it->second.first << " " << it->second.second << "\n";
}
Note the use of cbegin() and cend() functions.
Easier still, you can use the range-based for loop:
for(const auto& elem : myMap)
{
std::cout << elem.first << " " << elem.second.first << " " << elem.second.second << "\n";
}

If your compiler supports (at least part of) C++11 you could do something like:
for (auto& t : myMap)
std::cout << t.first << " "
<< t.second.first << " "
<< t.second.second << "\n";
For C++03 I'd use std::copy with an insertion operator instead:
typedef std::pair<string, std::pair<string, string> > T;
std::ostream &operator<<(std::ostream &os, T const &t) {
return os << t.first << " " << t.second.first << " " << t.second.second;
}
// ...
std:copy(myMap.begin(), myMap.end(), std::ostream_iterator<T>(std::cout, "\n"));

Since C++17 you can use range-based for loops together with structured bindings for iterating over your map. This improves readability, as you reduce the amount of needed first and second members in your code:
std::map<std::string, std::pair<std::string, std::string>> myMap;
myMap["x"] = { "a", "b" };
myMap["y"] = { "c", "d" };
for (const auto &[k, v] : myMap)
std::cout << "m[" << k << "] = (" << v.first << ", " << v.second << ") " << std::endl;
Output:
m[x] = (a, b)
m[y] = (c, d)
Code on Coliru

You can try range based loop like this:
for(auto& x:myMap){
cout<<x.first<<" "<<x.second.first<<" "<<x.second.second<<endl;
}

The easiest way is to declare an iterator first as
map<string ,string> :: iterator it;
and after that print it out by looping over the map using iterator from myMap.begin() to myMap.end() and print out key and value pairs in the map with it->first for key and it->second for value.
map<string ,string> :: iterator it;
for(it=myMap.begin();it !=myMap.end();++it)
{
std::cout << it->first << ' ' <<it->second;
}

Related

Why are my map values being reset after i exit a loop

I have a map named monthly_volumes within an object's member function and every time it finishes making the assignments to the map's value fields, the values are reset to 0(the value i initialized the map with before)
for (auto i : monthly_volumes) {
i.second = get_monthly_volume(i.first, year);
cout << "Month check during loop" << i.first << ":" << i.second << endl;
}
for (auto i : monthly_volumes) {
//i.second = get_monthly_volume(i.first, year);
cout << "Month Check After loop" << i.first << ":" << i.second << endl;
}
This is the
Output of the code
You need to iterate through the map with a reference, like this:
for (auto &i : monthly_volumes)
// changes to i, changes monthly_volumes
Also, in c++17 you could use structured bindings to make the code easier to read:
for (auto &[k, v] : monthly_volumes) {
v = get_monthly_volume(k, year);
cout << "Month check during loop" << k << ":" << v << endl;
}
You need a reference to the map entries to change them. Your code is changing a copy of the map entry.
for (auto& i : monthly_volumes) {
i.second = get_monthly_volume(i.first, year);
cout << "Month check during loop" << i.first << ":" << i.second << endl;
}

Keeping a reference to a vector element valid after resizing

If we make a reference to a vector element and then resize the vector, the reference is no longer valid, the same happens with an iterator:
std::vector<int> vec{0, 1, 2, 3, 4, 5};
int& ref = vec[0];
auto itr = vec.begin();
cout << ref << " " << *itr << endl;
vec[0] = 7;
cout << ref << " " << *itr << endl;
vec.resize(100);
vec[0] = 3;
cout << ref << " " << *itr << endl;
Prints out:
0 0
7 7
0 0 // We expected a 3 here
And I know that it would be more practical to just keep a reference to the vector itself and call vec[0], but just for the sake of questioning, is it possible to keep an object that will always be vec[0] even if the object is moved?
I've tried writing a small helper class to help with this, but I'm unsure if this is the best method or if it can even fail?
template<typename T>
struct HelperClass
{
std::vector<T>& vec;
size_t element;
HelperClass(std::vector<T>& vec_, size_t element_) : vec(vec_) , element(element_) {}
// Either define an implicit conversion from HelperClass to T
// or a 'dereference' operator that returns vec[0]
operator T&() { return vec.at(element); }
T& operator*() { return vec.at(element); }
};
And use it by either the implicit conversion to T& or by the 'dereference' operator:
std::vector<int> vec{0, 1, 2, 3, 4, 5};
int& ref = vec[0];
auto itr = vec.begin();
HelperClass<int> hlp = HelperClass<int>(vec, 0); // HelperClass
cout << ref << " " << *itr << " " << hlp << " " << *hlp << endl;
vec[0] = 7;
cout << ref << " " << *itr << " " << hlp << " " << *hlp << endl;
vec.resize(100);
vec[0] = 3;
cout << ref << " " << *itr << " " << hlp << " " << *hlp << endl;
Which already prints what was excepted:
0 0 0 0
7 7 7 7
0 0 3 3
So is there a better way to do this aside from having a helper class and can the helper class be unreliable in some cases?
I've also come across this thread in reddit, but it seems that they do not discuss the helper class there
The one thing you could do is have a vector of pointers rather than a vector of instances. That of course has its own passel of issues but if you must have object references survive a vector resize that will do it.
Any reallocation of the vector will invalidate any pointers, references and iterators.
In your example, your HelperClass is useless in sense that this:
cout << ref << " " << *itr << " " << hlp << " " << *hlp << endl;
is the same as:
cout << ref << " " << *itr << " " << vec[0] << " " << vec[0] << endl;
If a reallocation happens, just use the iterator interface .begin() .end() to access again the iterators.

How to output a map with a vector of pairs?

I have the following map;
std::map<long, std::vector<std::pair<long,long>>> G;
I'm having trouble figuring out how to print the pair values in it, could anyone help me out?
Try a loop:
for (const auto & p : G)
{
std::cout << p.first << " => {";
for (const auto & q : p.second)
std::cout << "(" << q.first << ", " << q.second << ")";
std::cout << "}\n";
}

std::cout for map<string, int>

I have a map declared as follows
map<string, int> symbolTable;
if(tempLine.substr(0,1) == "("){
symbolTable.insert(pair<string, int>(tempLine, lineCount));
}
How do I std::cout all of the things in my symbol table?
In modern C++:
for (auto&& item : symbolTable)
cout << item.first << ": " << item.second << '\n';
If you only have access to a pre-C++11 compiler the code would be:
for ( map<string, int>::const_iterator it = symbolTable.begin(); it != symbolTable.end(); ++it)
cout << it->first << ": " << it->second << '\n';
Here's an alternative if your compiler isn't C++11 compliant:
for (map<string, int>::iterator it = symbolTable.begin();
it != symbolTable.end(); ++it)
{
cout << it->first << " " << it->second << endl;
}
And for completeness, if it is:
for (auto& s : symbolTable)
{
cout << s.first << " " << s.second << endl;
}
You can use a loop to print all the key/value pairs. The code following is an example in C++11
for (const auto& kv : symbolTable) {
std::cout << kv.first << " " << kv.second << '\n';
}
ps: Both of other two answers pay little attention to const, which is quite sad...

in c++, iterator, why sometime I use it and sometimes use *it?

This one uses *it
int main ()
{
std::vector<int> myvector;
for (int i=1; i<=5; i++) myvector.push_back(i);
std::cout << "myvector contains:";
for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
This uses it.
for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
The syntax it->first is equivalent to (*it).first. In either case you're dereferencing the iterator.
The symantics of iterator is pointer. So imagine you have a pointer on each element. If you have a pointer it to an element of the vector, you can dereference it using * operator and get the element. The same is for pointer to the map element, which is a key/value pair. So dereferencing the pointer on a map element, you get std::pair. The key can be accessed by it->first or (*it).first, the value it->second or (*it).second.
for (std::map<char,int>::iterator it = mymap.begin(); it != mymap.end(); ++it)
std::cout << (*it).first << " => " << (*it).second << '\n';
or better use auto type deduction instead of writing iterator type explicitly (if your compiler supports C++11):
for (auto it = mymap.begin(); it != mymap.end(); ++it)
std::cout << (*it).first << " => " << (*it).second << '\n';
or even better use a new syntax (since C++11) as it is clearer and shorter:
for (const auto& elem: myvector)
std::cout << ' ' << elem;
for (const auto& elem: mymap)
std::cout << elem.first << " => " << elem.second << '\n';
They're equivalent. *it dereferences the iterator, and it-> does the same thing.
We could rewrite the second example to be:
for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << (*it).first << " => " << (*it).second << '\n';
// ^^^^^^ ^^^^^^
The -> operator is just cleaner in my opinion. Some people always use (*it) anyway. Purely style preference.
it is a pointer to the value (the iterator)
*it is the value
read: understanding-iterators-in-STL