I am getting compile error "map/set" iterator not dereferencable". What is going on here?
#include<iostream>
#include<map>
using namespace std;
int main(){
map<int, int> m;
map<int, int>::iterator itr=m.begin();
itr->first = 0;
itr->second = 0;
cout << itr->first << " " << itr->second;
return 0;
}
The map is empty, so m.begin() is equal to the past-the-end iterator and is therefore invalid.
You first have to insert elements somehow (you can also do that implicitly by using operator[]) to make it useful.
Also, you cannot modify the key of an element like this. You would have to remove (erase) the element from the map and insert a new one with the new key.
Here's an example about that:
#include<iostream>
#include<map>
using namespace std;
int main(){
map<int, int> m;
// insert element by map::insert
m.insert(make_pair(3, 3));
// insert element by map::operator[]
m[5] = 5;
std::cout << "increased values by one" << std::endl;
for(map<int, int>::iterator it = m.begin(); it != m.end(); ++it)
{
it->second += 1;
cout << it->first << " " << it->second << std::endl;
}
// replace an element:
map<int, int>::iterator thing = m.find(3);
int value = thing->second;
m.erase(thing);
m[4] = value;
std::cout << "replaced an element and inserted with different key" << std::endl;
for(map<int, int>::iterator it = m.begin(); it != m.end(); ++it)
{
cout << it->first << " " << it->second << std::endl;
}
return 0;
}
Your map's empty! What your iterator is pointing to is undefined.
What you wanted to do is
int main(){
map<int, int> m;
m[0] = 0;
map<int, int>::iterator itr=m.begin();
cout << itr->first << " " << itr->second;
return 0;
}
Here you have not assign any value. and you can not change the key of itr->first of it. It can be read only. But you can edit itr->second.
map<int, int> m;
m[10]=0;
map<int, int>::iterator itr=m.begin();
itr->second=10;
cout << itr->first << " " << itr->second;
Related
I am writing a program that reads team names from a file and divides them into groups. Each group of size 4. I am using a:
map<int, set<string> > groups
Assume the team names to be countries names.
Now after entering all the team names into the resp. groups I want to print the contents of each group and this is where I am getting stuck.
Here is the full working code, I have written so far.
#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
void form_groups(vector<string>);
int main(){
srand(unsigned(time(NULL)));
string team_name;
vector<string> teams;
while (cin >> team_name)
{
teams.push_back(team_name);
}
random_shuffle(teams.begin(), teams.end());
form_groups(teams);
}
void form_groups(vector<string> teams)
{
map<int, set<string> > groups;
map<int, set<string> >::iterator it;
string curr_item;
int curr_group = 1;
int count = 0;
for(int i = 0; i < teams.size(); i++)
{
curr_item = teams.at(i);
count++;
if(count == 4)
{
curr_group += 1;
count = 0;
}
groups[curr_group].insert(curr_item);
}
cout << curr_group << endl;
for(it = groups.begin(); it != groups.end(); ++it)
{
}
}
Your approach is fine. By using map<int, set<string> >::iterator it you can access a the given <key,value> pair with it->first and it->second. Since set<string> is a standard container itself you can use an set<string>::iterator to traverse through the elements:
map<int, set<string> >::iterator map_it;
set<string>::iterator set_it
for(map_it = groups.begin(); map_it != groups.end(); ++map_it){
cout << "Group " << it->first << ": ";
for(set_it = map_it->second.begin(); set_it != map_it->second.end(); ++set_it)
cout << *set_it << " ";
cout << endl;
}
I think it is the iteration over the groups map that is your difficulty. Example of iterating over a map:
for (it = groups.begin(); it != groups.end(); it++)
{
// 'it->first' is the 'int' of the map entry (the key)
//
cout << "Group " << it->first << "\n";
// 'it->second' is the 'set<string>' of the map entry (the value)
//
for (set<string>::iterator name_it = it->second.begin();
name_it != it->second.end();
name_it++)
{
cout << " " << *name_it << "\n";
}
}
While iterating over a std::map<..>, it->first would give you the key, and it->second would give you the corresponding value.
You would need something like this to iterate over the map:
for(it = groups.begin(); it != groups.end(); ++it)
{
cout<<"For group: "<<it->first<<": {"; //it->first gives you the key of the map.
//it->second is the value -- the set. Iterate over it.
for (set<string>::iterator it2=it->second.begin(); it2!=it->second.end(); it2++)
cout<<*it2<<endl;
cout<<"}\n";
}
As the title says I want to print out all the elements of "group1" in this 2D map. I tried this but I just get a huge error at the for loop.
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main(){
map<string,map<int,double> > myMap;
myMap["group1"][13] = 10.41;
myMap["group1"][15] = 31.2;
//print all elements in "group1"
for (map< string, map<int,double> >::const_iterator iter =
myMap["group1"].begin(); iter != myMap["group1"].end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
return 0;
}
Any help would be appreciated, thanks!
The type of myMap["group1"] is map<int,double> and not map<string,map<int,double>>
Then your code would look somehow like this:
const map<int,double> &grp1map = myMap["group1"];
for (map<int,double>::const_iterator iter = grp1map.begin(); iter != grp1map.end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
You can simplify this with auto:
auto &grp1map = myMap["group1"];
for (auto iter = grp1map.begin(); iter != grp1map.end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
But anyway you should do it like this:
for (auto &elem : myMap["group1"] )
{
cout << elem.first << '\t' << elem.second << '\n';
}
You want an iterator to your internal map<int,double>, whereas you are trying to get and iterator to your outer map<string,map<int,double> >:
int main() {
map<string, map<int, double> > myMap;
myMap["group1"][13] = 10.41;
myMap["group1"][15] = 31.2;
//print all elements in "group1"
for (map<int, double>::const_iterator iter =
myMap["group1"].begin(); iter != myMap["group1"].end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
return 0;
}
Since map is implemented using a tree and hash_map using a hash, I created a code to test if my map would give me an ordered result and the hash_map would print my examples in the order that they were registered
map<string, int> mymap;
hash_map<string, int> myhashmap;
mymap["lucas"] = 1;
mymap["abel"] = 2;
mymap["jose"] = 1;
myhashmap["lucas"] = 1;
myhashmap["abel"] = 2;
myhashmap["jose"] = 1;
for(map<string, int>::iterator it = mymap.begin(); it != mymap.end(); it++){
cout << it->first << " " << it->second << endl;
}
cout << endl;
for(hash_map<string, int>::iterator it = myhashmap.begin(); it != myhashmap.end(); it++){
cout << it->first << " " << it->second << endl;
}
but both results were:
abel 2
jose 1
lucas 1
why the hash_map gave me an ordered result?
There is no order guarantee in hash_map - which means it can store results in any order, depending on implementation.
I am trying to display the contents of a multimap with a string and a vector as key and value, respectively. I run into problems when I try to dislpay the contents of the vector (value in multimap). What I have done so far is:
multimap<string, vector<string> > someMultimap;
vector<string> someVector;
someVector.push_back("test");
someMultimap.insert(pair<string, vector<string> >("KEY", someVector));
//So for it works fine...
multimap <string, vector<string> >::iterator it;
for (it = someMultimap.begin(); it != someMultimap.end(); ++it)
{
cout << it->first << endl << endl << it->second << endl << endl;
^^^^^^^^^^
this is the problem, canĀ“t do this with a vector(?)
}
Does anyone have a suggestion for solving the problem?
You can add a second loop for the vector.
multimap <string, vector<string> >::const_iterator it;
for (it = someMultimap.begin(); it != someMultimap.end(); ++it)
{
cout << it->first << endl ;
vector<string>::const_iterator itVec;
for (itVec = it->second.begin(); itVec != it->second.end(); ++itVec)
{
cout << *itVec <<" ";
}
cout<<endl;
}
If you don't plan to modify any value you can make your iterators const
Use std::copy to output the vector's contents with a single function:
#include <iterator>
#include <algorithm>
#include <iostream>
//..
using namespace std;
for (it = someMultimap.begin(); it != someMultimap.end(); ++it)
{
cout << it->first << "\n\n";
copy(it->second.begin(), it->second.end(), ostream_iterator<string>(cout, " "));
cout << "\n\n";
}
Loop through the vector and print:
cout << it->first << endl << endl;
for (vector<string>::iterator j(it->second.begin()); j != it->second.end(); ++j)
cout << *j << " ";
cout << endl << endl;
Also, don't use std::endl, it flushes on each call which can hinder performance.
Well, you can define what it means to send a std::vector to a std::ostream.
Here's an example of one way to do it:
template<typename T>
std::ostream& operator <<(std::ostream& stream, std::vector<T> const& v) {
for (auto&& e : v) {
stream << e << ' ';
}
return stream;
}
I am writing a program that reads team names from a file and divides them into groups. Each group of size 4. I am using a:
map<int, set<string> > groups
Assume the team names to be countries names.
Now after entering all the team names into the resp. groups I want to print the contents of each group and this is where I am getting stuck.
Here is the full working code, I have written so far.
#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
void form_groups(vector<string>);
int main(){
srand(unsigned(time(NULL)));
string team_name;
vector<string> teams;
while (cin >> team_name)
{
teams.push_back(team_name);
}
random_shuffle(teams.begin(), teams.end());
form_groups(teams);
}
void form_groups(vector<string> teams)
{
map<int, set<string> > groups;
map<int, set<string> >::iterator it;
string curr_item;
int curr_group = 1;
int count = 0;
for(int i = 0; i < teams.size(); i++)
{
curr_item = teams.at(i);
count++;
if(count == 4)
{
curr_group += 1;
count = 0;
}
groups[curr_group].insert(curr_item);
}
cout << curr_group << endl;
for(it = groups.begin(); it != groups.end(); ++it)
{
}
}
Your approach is fine. By using map<int, set<string> >::iterator it you can access a the given <key,value> pair with it->first and it->second. Since set<string> is a standard container itself you can use an set<string>::iterator to traverse through the elements:
map<int, set<string> >::iterator map_it;
set<string>::iterator set_it
for(map_it = groups.begin(); map_it != groups.end(); ++map_it){
cout << "Group " << it->first << ": ";
for(set_it = map_it->second.begin(); set_it != map_it->second.end(); ++set_it)
cout << *set_it << " ";
cout << endl;
}
I think it is the iteration over the groups map that is your difficulty. Example of iterating over a map:
for (it = groups.begin(); it != groups.end(); it++)
{
// 'it->first' is the 'int' of the map entry (the key)
//
cout << "Group " << it->first << "\n";
// 'it->second' is the 'set<string>' of the map entry (the value)
//
for (set<string>::iterator name_it = it->second.begin();
name_it != it->second.end();
name_it++)
{
cout << " " << *name_it << "\n";
}
}
While iterating over a std::map<..>, it->first would give you the key, and it->second would give you the corresponding value.
You would need something like this to iterate over the map:
for(it = groups.begin(); it != groups.end(); ++it)
{
cout<<"For group: "<<it->first<<": {"; //it->first gives you the key of the map.
//it->second is the value -- the set. Iterate over it.
for (set<string>::iterator it2=it->second.begin(); it2!=it->second.end(); it2++)
cout<<*it2<<endl;
cout<<"}\n";
}