Getting strange error while trying to set up an iterator - c++

This is probably a silly error but I can't seem to find what I have done wrong.
The error I am getting is no operator "=" matches these operands.
Here is my code...
void print_words(const map < string, int >& m1) {
map<string, int>::iterator it;
cout << "Number of non-empty words: " << m1.size() << '\n';
int count = 0;
for (it = m1.begin(); it != m1.end(); it++) {
}
}
I get the error in the for loop in the it = m1.begin() statement and I cannot go on to print out the map if I can't iterate through it.

Use a const iterator:
void print_words(const map < string, int >& m1) {
cout << "Number of non-empty words: " << m1.size() << '\n';
int count = 0;
for (map<string, int>::const_iterator it = m1.cbegin(); it != m1.cend(); it++) {
}
}

Use a const_iterator or auto.
void print_words(const map < string, int >& m1) {
cout << "Number of non-empty words: " << m1.size() << '\n';
int count = 0;
for (auto it = m1.cbegin(); it != m1.cend(); it++) {
}
}

Related

How do I loop through a unordered_map in C++ without auto?

I am trying to loop through an unordered_map, to find if any of its VALUES is greater than 2. But this syntax is wrong
unordered_map<int, int> mp;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
for (int i = 0; i < mp.size(); i++ ) {
cout << mp[i].second << " " << endl; //mp[i].second is wrong syntax
if (mp[i].second > 2) {
cout << "WRONG";
x = false;
break;
}
}
how can I do this?
It seems that you assumed(incorrectly) that mp[i] is std::pair<int, int> when in fact mp[i] gives you the mapped value which is of type int in your example. This can be seen from std::map::operator[]:
T& operator[]( Key&& key ); (2)
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
(emphasis mine)
Method 1
Since you don't want to use auto, you can explicitly write the type std::pair<int, int> in the range-based for loop as shown below:
//---------vvvvvvvvvvvvvvvvvvvvvvvv--------------------->not using auto here as you want
for (const std::pair<const int, int> &pair_elem: mp) {
cout << pair_elem.second << " " << endl;
if (pair_elem.second > 2) {
cout << "WRONG";
//other code here
}
}
Method 2
Note that you can also use std::find_if instead of a for loop as shown below:
auto iter = std::find_if(mp.begin(), mp.end(), [](const std::pair<int,int>& elem)
{ return elem.second > 2;});
if (iter != mp.end())
std::cout << "Greater found ";
else
{
std::cout<<"Greater not found"<<std::endl;
}
Demo
your question is missing a lot of information and literarily , if you searched on web , you would find many ways to loop over unordered_map in C++ , but anyways , here is the edited version of your code with a test case:
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
const int N = 10;
int arr[N] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
bool x = true;
unordered_map<int, int> mp;
unordered_map<int, int>:: iterator it;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
mp[9] = 5;
for (it = mp.begin(); it != mp.end(); it++) {
cout << "key is " << it->first << " ,value is " << it->second << " " << endl;
if (it -> second > 2) {
cout << "WRONG";
x = false;
cout << "key is " << it->first << " ,value is " << it->second << " is greater than 2" << endl;
break;
}
}
return 0;
}

printing a value of map which has two string as key and vector as value

I have a map which has two string as key and one vector as value
how can i print the value of map.
Below is my approach which is bad Can Someone help me thanks in advance
NOTE : i want to print by key not iterating on vector
int main()
{
vector<string>value;
std::map<std::pair<string,string> ,vector<string>> myMap;
string input1,input2,MyvectorValue;
for(int i=0;i<5;++i)
{
cin>>input1;
cin>>input2;
cin>>MyvectorValue;
myMap[std::make_pair(input1,input2)].push_back(MyvectorValue);
}
int j=0;
for( auto it = myMap.begin(); it != myMap.end(); ++it )
{
std::vector<std::string>& value = it->second.at(j++);
cout<<value // This is bad
//how can i print all map value ??
}
}
The value of the map is a vector, assuming you can use C++11, the following code would do what you need.
#include <string>
#include <iostream>
#include <map>
#include <utility>
#include <vector>
int main()
{
std::vector< std::string >value;
std::map< std::pair<std::string , std::string> , std::vector<std::string> > myMap;
std::string input1,input2,MyvectorValue;
for(int i=0;i<5;++i)
{
std::cin>>input1;
std::cin>>input2;
std::cin>>MyvectorValue;
myMap[std::make_pair(input1,input2)].push_back(MyvectorValue);
}
//If you have a particular key (string1, string2), and want to print the values for that specific key...
auto particularKey = std::make_pair("stringA", "stringB");
for(auto val : myMap[particularKey])
std::cout << val << " ";
std::cout << std::endl;
// If you want to iterate through all keys of your map
for(auto &elem : myMap)
{
std::cout << "for the pair with key (" << elem.first.first << "," << elem.first.second << "), the value is the following vector" << std::endl;
for(auto s : elem.second)
{
std::cout << s << " ";
}
std::cout << std::endl << std::endl;
}
return 0;
}
You can print the keys by accessing the pair and then using first and second to get the first and second member of the pair respectively.
You can also print the values, by accessing the vectors and iterating over them, printing every string separately.
for(auto& element : myMap)
{
std::cout << "Key: {" << element.first.first << ", " << element.first.second << "}\n";
std::cout << "Value is a vector with the following strings: \n";
for(auto& str: element.second)
std::cout << str << std::endl;
}
If you want to print by key not iterating on vector , then you may declare map as "std::map,string> myMap". Then, you can do following modification to your code as given below.
int main() {
vector<string>value;
std::map<std::pair<string,string>,string> myMap;
string input1,input2,MyvectorValue;
for(int i=0; i<5; ++i) {
cin>>input1;
cin>>input2;
cin>>MyvectorValue;
myMap[std::make_pair(input1,input2)]+=MyvectorValue;
myMap[std::make_pair(input1,input2)]+= " ";
}
for( auto it = myMap.begin(); it != myMap.end(); ++it ) {
std::string& value = it->second;
cout<<value<<endl;
}
}

map/set iterator not dereferencable. Multimap container isse

I'm geting this error message map/set iterator not dereferencable When trying to get value by key in multimap. In this code I'm trying to show nonoriented graph represented by adjacency list (vector<Vertex*> vertexList)
void NonOrGraph::show() {
cout << endl;
multimap<int, int> used;
for (int i = 0; i < vertexList.size(); i++) {
if (vertexList[i]->adjMap.empty()) {
cout << vertexList[i]->index << " isolated";
} else {
for(map<Vertex*, int>::iterator it = vertexList[i]->adjMap.begin();
it != vertexList[i]->adjMap.end();
it++)
{
int from = vertexList[i]->index;
int to = it->first->index;
int weight = it->second;
used.insert(pair<int, int>(from, to));
if (used.find(to)->second != from) {
cout << from << " <--(" << weight << ")--> " << to << endl;
}
}
}
}
cout << "\n\n";
}
The problem is likely here:
if (used.find(to)->second != from) {
If to is not in used, used.find() will return used.end(), which you then dereference. It is undefined behavior to dereference the end() iterator, which in this case manifests by giving you a runtime error.
You have to check the iterator against end() first:
std::multimap<int, int>::iterator multi_it = used.find(to);
if (multi_it != used.end() && multi_it->second != from) {
// ^^^^^^^^^^^^^^^^^^^^
// now, it's safe to dereference

How can I print the content of map<string, map<int, int>> to cout?

How can I print the contents of a nested map? I am counting the number of times a word appears in a file, reporting it by line number and number of times per line. The words, lines, and occurrences per line are being stored in the following container:
map<string, map<int, int>> tokens;
However, I'm not sure on the syntax. I am printing the outer map that lists all of the words using the following code, but can't figure out how to print the inner values (the line number and number of times the word appears on each line) as well. I assume I can just include it inline in the for loop, but I can't figure out how:
for (map <string, map<int, int>>::iterator it = tokens.begin(); it != tokens.end(); ++it){
cout << it->first << " : " << /* assume I can include another statement here to print the values? */ endl;
}
I am trying to get an output similar to this:
(word : line:occurrences, line:occurrences, ...)
about : 16:1, 29:1, 166:1, 190:1, 191:1
above : 137:1
accompanied : 6:1
across : 26:1
admit : 20:1
advancing : 170:1
.
.
.
It is actually pretty simple.
You just get the internal map with it->second, and you iterate through that the same way.
Thereby, you would write something like this:
for (map <string, map<int, int>>::iterator it = tokens.begin(); it != tokens.end(); ++it){
cout << it->first << " : ";
map<int, int> &internal_map = it->second;
for (map<int, int>::iterator it2 = internal_map.begin(); it2 != internal_map.end(); ++it2){
if (it2 != internal_map.begin())
cout << ",";
cout << it2->first << ":" << it2->second;
}
cout << endl;
}
You could write something like this if you have C++11 support:
for (auto it : tokens) {
cout << it->first << " : ";
map<int, int> &internal_map = it->second;
for (auto it2: internal_map) {
if (it2 != internal_map.begin())
cout << ",";
cout << it2->first << ":" << it2->second;
}
cout << endl;
}
C++17
Since C++17 you can use range-based for loops together with structured bindings for iterating over maps.
This way, the readability of lpapp's C++11 solution can be further improved as follows:
for (auto const &[k1, v1] : tokens) {
std::cout << k1 << " : ";
for (auto const &[k2, v2] : v1) {
if (&k2 != &v1.begin()->first)
std::cout << ", ";
std::cout << k2 << ":" << v2;
}
std::cout << std::endl;
}
Note: I admit, the check for printing a comma is a bit messy. If you are looking for a nicer solution, you
might want to take a look at this Q&A.
Code on Coliru
Since we are only printing the elements, not modifying it, I would make more use of const, (a) const reference and (b) const iterators.
Also, for pre-C++11, it helps to define typedef's for complex types.
#include <string>
#include <map>
#include <iostream>
using namespace std;
typedef map<int, int> InnerMap;
typedef map<string, InnerMap> OuterMap;
void printClassic( OuterMap const & tokens ) {
for( OuterMap::const_iterator cit = tokens.begin();
cit != tokens.end(); ++cit ) {
cout << cit->first << " : ";
InnerMap const & imap = cit->second;
for( InnerMap::const_iterator cit2 = imap.begin();
cit2 != imap.end(); ++cit2 ) {
cout << cit2->first << ":" << cit2->second << ",";
}
cout << endl;
}
}
void printCpp11( OuterMap const & tokens ) {
for( auto const & cit : tokens ) {
cout << cit.first << " : ";
auto const & imap = cit.second;
for( auto const & cit2 : imap ) {
cout << cit2.first << ":" << cit2.second << ",";
}
cout << endl;
}
}

How to print a vector array?

I have a vector array called nVectors.
vector<int>* nVectors[21];
for (int i = 1; i <= 20; i ++) {
nVectors[i] = generateVector(i);
}
I can print all the members of a single vector, but when it comes to the vector array, I still don't know how to print all the vectors in an array.
Maybe an iterator through all the member of a vector array and print using my predefined method pvector can solve this problem? But I don't know how to iterate in gdb.
std::array<std::vector<int>*, 21> nVectors;
for(std::array<std::vector<int>*>::iterator i = nVectors.begin();
i != nVectors.end();
++i)
{
for(std::vector<int>::iterator it = (*i)->begin();
it != (*i)->end();
++it)
{
std::cout << *it << " ";
}
}
std::cout << std::endl;
Or, in C++11:
std::vector<int>* nVectors[21];
for(auto &i : nVectors)
{
for(auto &it : i)
{
std::cout << *it << " ";
}
}
std::cout << std::endl;