cannot print pointer to element of unordered_map - c++

I've installed CodeBloks and I was testing it with a simple problem.
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<int,int> mp;
mp[1]=2;
mp[2]=3;
for(unordered_map<int,int>::iterator it = mp.begin();it!=mp.end();it++)
cout<<*it<<" ";
return 0;
}
I get this error:
cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'

Taken from cppreference
for( const auto& n : u ) {
std::cout << "Key:[" << n.first << "] Value:[" << n.second << "]\n";
}
A map (unordered or not) is composed of a key, and a value. You can access it with first and second from the iterator.

The error may be misleading. The actual problem is that unordered map iterates in pairs of keys and values, and there is no << operator for printing these pairs directly.
You can access the key through it->first and the value through it->second:
for(unordered_map<int,int>::iterator it = mp.begin();it!=mp.end();it++)
cout<<it->first << " " << it->second << endl;
Demo.

A map stores key/value-pairs, and it provides a member first (standing for the key) and a member second (standing for the value). Try the following cout...-statement:
cout << it->first << ":" << it->second << " ";

Structured bindings would work nicely for this:
for(auto [first, second] : mp) {
cout << first << '\t' << second << '\n';
}

Related

Two instances of keyword auto in cpp

First one being:
map <int,int> m;
//... some elements inserted
auto i= m.begin();
cout<<(*i).first<<(*i).second;
Here we are required to use the dereference operator *
Second:
map <int,int> m;
//... some elements inserted
for(auto i: m)
cout<<i.first<<i.second;
Why am I not required to use the * operator this time?
One more doubt:
for(auto &i: m)
what difference does '&' make here?
auto i=m.begin() will give you iterator .. which is accessed more like a pointer (syntactically) when you want to access the value...
for(auto i:m) will copy current element of m (a pair) into i , i is a copy of element, not the element itself...
for (auto &i: m) will work on a reference, the original map is affected
As explained in the below code snippet, the first i is of type iterator where as the i in the for loops are of pair type.
#include <iostream>
#include <map>
int main()
{
std::map <int,int> m;
m[1] = 5;
m[10] = 60;
m[100] = 800;
// Below i is map iterator (std::map<int, int>::iterator)
auto i = m.begin();
std::cout << typeid(i).name() << '\n';
std::cout << (*i).first << " : " << (*i).second << '\n';
std::cout << i->first << " : " << i->second << '\n';
for(auto i: m) {
// Below i is pair<int, int>
std::cout << typeid(i).name() << '\n';
std::cout << i.first << " : " << i.second << '\n';
}
for(auto& i: m) {
// Below i is reference of pair<int, int>)
// modifying this would result in updated values in the map.
std::cout << typeid(i).name() << '\n';
std::cout << i.first << " : " << i.second << '\n';
}
return 0;
}

how to print the contents of the vector to screen in c++ whose each element is pair in a pair

I am working on a assignment in which the elements of the vector of this type vector<pair<string,pair<int,int> > > A .
for(auto it=A.begin();it!=A.end();it++)
cout <<*it.first<<" "<< *it.second.first <<" "<<*it.second.second;
but it is showing errors.
Can anyone help me?
This is much, much simpler with modern C++ language features (C++17):
for (const auto &[s, p] : A)
{
const auto &[a, b] = p;
std::cout << s << " " << a << " " << b << std::endl;
}
If your C++ textbook and/or compiler doesn't cover C++17, it is really worth one's time to update your documentation and/or your compiler to the current C++ standard.
you need to use (*it).first instead of *it.first, because *it.first means a iterator which is it.first, but actually the iterator is (*it).
You can get rid of this problem by using ->, like it->first. Because if you use -> it is lot easier than using *.
vector<pair<string,pair<int,int> > > A;
for(auto it = A.begin(); it != A.end(); it++){
//cout << (*it).first << " " << (*it).second.first << " " << (*it).second.second;
cout << it->first << " " << it->second->first << " " << it->second->second;
}
You can use range-based loop instead of iterators to avoid the problems with *:
for(const auto& itr:A)
{
std::cout<< "Base Pair 1st: "<<itr.first<<" level pair 1st:"<<itr.second.first<<" level pair 2nd "<<itr.second.second;
}

Is map::find safe?

I'm trying to test if "find" is safe in std:map so I've erased an element after I use "find" to test it but the iterator to the element is still valid. Even if I use find again it finds the erased element again.
According to documentation:
Iterators, pointers and references referring to elements removed by the function are invalidated.
All other iterators, pointers and references keep their validity.
Why does the second iterator auto it_2 = numeros.find("uno"); finds the element if it was erased?
Why does std::cout << it->first << " : " << it->second << std::endl; after "erase" prints the element? It means find is safe when the element is removed from the map?
This is my example.
#include <iostream>
#include <map>
int main(int argc, char *argv[])
{
std::map<std::string,unsigned int> numeros = { {"uno",1}, {"dos",2}, {"tres",3}};
auto it = numeros.find("uno");
std::cout << it->first << " : " << it->second << std::endl;
std::cout << std::endl;
numeros.erase("uno");
std::cout << it->first << " : " << it->second << std::endl;
std::cout << std::endl;
auto it_2 = numeros.find("uno");
std::cout << it_2->first << " : " << it_2->second << std::endl;
std::cout << std::endl;
for (auto i=numeros.begin(); i!=numeros.end(); ++i)
std::cout << i->first << " : " << i->second << std::endl;
return 0;
}
Output
uno : 1
uno : 1
uno : 1
dos : 2
tres : 3
Thank you!
numeros.erase("uno"); invalidates the iterator it as per your quote. This means that you are not allowed to dereference the iterator anymore. Doing so anyway has undefined behavior.
Therefore your program has undefined behavior because you dereference the iterator in the next line
std::cout << it->first << " : " << it->second << std::endl;
Undefined behavior means your program could do anything. There are no guarantees that anything specific will happen anymore. There are no guarantees that you will get any error or warning either.
(Assuming you corrected the undefined behavior above:)
The second find in
auto it_2 = numeros.find("uno");
does not find the erased element. If .find does not find any element it returns the past-the-end iterator numeros.end(), which is what is happening here. Dereferencing the past-the-end iterator also has undefined behavior. So the following line
std::cout << it_2->first << " : " << it_2->second << std::endl;
which dereferences the past-the-end iterator also causes undefined behavior and your program to have no behavior guarantees.
You need to always check the result of find against end to verify that it found an element:
if(it_2 != numeros.end()) {
std::cout << it_2->first << " : " << it_2->second << std::endl;
} else {
std::cout << "uno not found!" << std::endl;
}

Issue with output for nested std::map

std::map<int, std::map<std::string, std::pair<int, std::string>>>mfvs;
I want to output the std::string the first part of inner map.
for (const auto& iter :mfvs)
{
std::cout << iter.second.first << "\n";
}
this gives me an error
iter.second is an std::map, and as such it doesn't have first.
If you want to print the first (with lowest key) element (and you are sure it exists), then do this:
std::cout << iter.second.begin()->first << "\n";
.begin() will return you the first element of the map, and ->first will get its key. If you want to print the value of it as well, something along the lines of the following code will work
auto firstElem = iter.second.begin();
std::cout << firstElem->first << ": " << firstElem->second.first << ", " << firstElem->second.second << "\n";

unordered_map pair of values c++

I am trying to use the unordered_map in C++, such that, for the key I have an int, while for the value there is a pair of floats. But, I am not sure how to access the pair of values. I am just trying to make sense of this data structure. I know to access the elements we need an iterator of the same type as this unordered map declaration. I tried using iterator->second.first and iterator->second.second. Is this the correct way to do access elements?
typedef std::pair<float, float> Wkij;
tr1::unordered_map<int, Wkij> sWeight;
tr1::unordered_map<int, Wkij>:: iterator it;
it->second.first // access the first element of the pair
it->second.second // access the second element of the pair
Thanks for your help and time.
Yes, this is correct, but don't use tr1, write std, since unordered_map is already part of STL.
Use iterators like you said
for(auto it = sWeight.begin(); it != sWeight.end(); ++it) {
std::cout << it->first << ": "
<< it->second.first << ", "
<< it->second.second << std::endl;
}
Also in C++11 you can use range-based for loop
for(auto& e : sWeight) {
std::cout << e.first << ": "
<< e.second.first << ", "
<< e.second.second << std::endl;
}
And if you need it you can work with std::pair like this
for(auto it = sWeight.begin(); it != sWeight.end(); ++it) {
auto& p = it->second;
std::cout << it->first << ": "
<< p.first << ", "
<< p.second << std::endl;
}