std::map<int,bool> wrong result of insert? - c++

#include <iostream>
#include <map>
using namespace std;
int main()
{
std::map<int, bool> set;
cout << (int)set.insert({ 5,false }).second << endl;
return 0;
}
I don't know why the result is 1 instead of 0, while second is false.

std::map::insert's return value is an std::pair<iterator, bool> where the bool denotes whether insertion took place. cout << (int)set.insert({ 5,false }).second << endl; will only print whether insertion successfully took place.
To do what you want, you'll want to use the first value in the returned std::pair which is an iterator and then use that to check the value of the new key/value pair that you inserted:
#include <iostream>
#include <map>
int main()
{
std::map<int, bool> set;
std::cout << set.insert({5, false}).first->second << '\n';
return 0;
}

Related

C++11 search an std::map with composite key

I want to implement a function (findn) below that search on the std::map to find an element. However in my case the key is composite value, it is an <int,int>
How do I use the std::map.find here?
#include <iostream>
#include <map>
#include <utility>
#include <string>
using namespace std;
std::map<std::pair<int, int>, std::string> studentMap;
int insert(int i, int j, std::string name) {
if( !studentMap.insert( std::make_pair ( std::make_pair(i,j), name)).second ) {
std::cout << "game not added" << std::endl;
} else {
std::cout << "game added" << std::endl;
}
return 0;
}
void findn(int i, int j) {
// how to find when we have composite key?
}
int main() {
insert(1,1,"test");
insert(1,1,"tes");
insert(1,2,"test 2");
std::cout << studentMap.size() << std::endl;
findn(1,1);
}
This would do the work:
auto it = mymap.find(std::make_pair(i,j));

Multi Set as a class template using list functions as basis

The basis of the program is a header file that defines the template class miniMultiSet. The class uses the list structure as the implementation structure for the multiset. The class is implemented in the header file by implementing the defined class methods.
When I do this I am running into issues sending the information from main.cpp to my header file. There are not error messages, it just freezes and I have to close it. This makes me think I have an error in my memory management.
HEADER FILE:
#ifndef MINIMULTISET_H_INCLUDED
#define MINIMULTISET_H_INCLUDED
#include <list>
#include <set>
using namespace std;
template <typename T>
class miniMultiSet
{
public:
typedef typename list<T>::iterator iterator;
typedef typename list<T>::const_iterator const_iterator;
// miniMultiSet iterators are simply list iterators
miniMultiSet();
// default constructor
bool empty() const{return l.empty();}
// is the multiset empty?
int size() const{return l.size();}
// return the number of elements in the multiset
iterator insert(const T& item)
{
l.insert(l.end(), item);
return l.end();
}
// insert item into multi set and return an
// iterator pointing at the new element.
private:
list<T> l;
// multiset implemented using a list
};
#endif // MINIMULTISET_H_INCLUDED
main.cpp //////////////////////////////////////////////
#include <iostream>
#include <list>
#include <set>
#include <algorithm>
#include "miniMultiSet.h"
using namespace std;
int main()
{
miniMultiSet<int> *A;
A=0;
*A->insert(90);
cout << A->size() << endl;
if(A->empty())
cout << "Set is empty." << endl;
else
cout << "Set contains data." << endl;
return 0;
}
I build it and there are no error statements. When I run it I get "Program has stopped working, searching for a solution.". It then ends the program and I get "Process returned -1073741819 (0xC0000005) execution time: 4.421 s. Press any key to continue."
I am not sure how to fix this, any advice would be greatly appreciated.
Your problem is that you cannot ever construct a miniMultiSet because you declared its default constructor but never defined it. It seems like you should simply remove your default constructor declaration, as the compiler-generated one will work fine, and then do miniMultiSet<int> A without a pointer.
The code above altered to make a multiset operate like a list.
HEADER FILE:
#ifndef MINIMULTISET_H_INCLUDED
#define MINIMULTISET_H_INCLUDED
#include <list>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;
template <typename T>
class miniMultiSet
{
public:
typedef typename list<T>::iterator iterator;
typedef typename list<T>::const_iterator const_iterator;
// miniMultiSet iterators are simply list iterators
//miniMultiSet();
// default constructor
bool empty() const{return l.empty();}
// is the multiset empty?
int size() const{return l.size();}
// return the number of elements in the multiset
int count (const T& item)
{
int tally = 0;
std::list<int>::iterator is;
for(is=l.begin();is!=l.end();++is)
{
if(*is==item)
tally++;
}
return tally;
}
// return the number of duplicate occurrences of item
// in the multiset
iterator find (const T& item)
{
std::list<int>::iterator it;
for(it=l.begin();it!=l.end();++it)
{
if(*it==item)
break;
}
return it;
}
// search for item in the multiset and return an iterator
// pointing at the first occurrence matching item, or end()
// if it is not found
const_iterator find (const T& item) const
{
int count=0;
std::list<int>::iterator it;
for(it=l.begin();it!=l.end();++it)
{
if(*it==item)
break;
}
}
// constant version
iterator insert(const T& item)
{
l.insert(l.end(), item);
return l.end();
}
// insert item into multi set and return an
// iterator pointing at the new element.
int erase(const T& item)
{
int count=0;
std::list<int>::iterator it;
std::list<int>::iterator il;
for(it=l.begin();it!=l.end();++it)
{
if(*it==item)
{
it=l.erase((it));
it--;
++count;
}
}
return count;
}
// erase all occurrences of item from the multi set
// and return the number of items erased.
iterator begin(){return l.begin();}
// return an iterator pointing at the first member
// in the multiset
const_iterator begin() const{return l.cbegin();}
// constant version
iterator end(){return l.end();}
// return an iterator pointing just past the last
// member in the muktiset
const_iterator end() const{return l.cend();}
// constant version
private:
list<T> l;
// multiset implemented using a list
};
#endif // MINIMULTISET_H_INCLUDED
MAIN CPP FILE
#include <iostream>
#include <list>
#include <set>
#include <algorithm>
#include "miniMultiSet.h"
using namespace std;
int main()
{
miniMultiSet<int> A;
A.insert(80);
A.insert(90);
A.insert(90);
A.insert(90);
A.insert(95);
A.insert(100);
A.insert(105);
A.insert(110);
A.insert(115);
A.insert(120);
if(A.empty())
cout << "Set is empty." << endl;
else
cout << "Set is NOT empty." << endl;
cout << endl;
cout << endl;
cout << "This size of the Multi Set is: " << A.size() << endl;
cout << endl;
cout << endl;
cout << "The first element is: " << *A.begin() << endl;
if(A.find(90)!=A.end())
cout << "90 was found" << endl;
cout << endl;
cout << endl;
cout << "90 was found " << A.count(90) << " times." << endl;
cout << endl;
cout << endl;
//pair<int, int>(90);
cout << "90 was found " << A.erase(90) << " times and erased." << endl;
cout << endl;
cout << endl;
cout << "This size of the Multi Set is: " << A.size() << endl;
cout << endl;
cout << endl;
cout << "90 was found " << A.count(90) << " times." << endl;
return 0;
}
Not the prettiest or most efficient, but it works. Thank you for all the help.

map and unordered_map containing pointers to double?

If I have a std::map and std::unordered_map how could I use pointers on the double so that when the unordered_map updates the double value for a particular key, this is already reflected in the std::map for the same "key"?
So:
unordered_map["1"] = 6 causes map["1"] to be 6 also....
There's no reason why you can't use pointers.
Example:
#include <iostream>
#include <map>
#include <unordered_map>
#include <memory>
int main()
{
std::unordered_map<std::string, std::shared_ptr<double>> umap;
std::map<std::string, std::shared_ptr<double>> omap;
std::shared_ptr<double> value(new double(1234.5));
umap.emplace("key", value);
omap.emplace("key", value);
std::cout << "umap " << *umap["key"] << "\n";
std::cout << "omap " << *omap["key"] << "\n";
*umap["key"] = 9999.1;
std::cout << "omap " << *omap["key"] << "\n";
}
Output:
umap 1234.5
omap 1234.5
omap 9999.1
Maybe like this:
std::unordered_map<std::string, double> um;
std::unordered_map<std::string, double*> om;
om["1"] = &um["1"];
From now on, *om["1"] is always the value of the corresponding element in um. Just make sure you never delete elements from the unordered map.
(Source: iterator and reference invalidation rules)

Checking if vector 'space' in vector<vector<queue<msg>>> is empty

I am playing around with containers, and at the moment trying to use a vector<vector<queue<int>>>. The form of this container is such that the 'first' vector's index is client ID, 'second' vector's index is priority level. i.e. a message of type int is pushed into a queue of certain priority, belonging to a certain client.
I am trying to find an easy way to find out if a client has any messages i.e. if any of it's priority levels has a non-empty queue. I used this simple piece of code to illustrate what I am trying to do:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int main()
{
vector<vector<queue<int>>> node_pri_msg;
queue<int> pri_msg;
node_pri_msg.resize(2);
node_pri_msg[1].resize(2);
node_pri_msg[0].resize(2);
for (int i=0; i<2; i++)
{
node_pri_msg[i].push_back(pri_msg);
}
node_pri_msg[0][1].push(3);
if (node_pri_msg[1].empty())
{
cout << "empty-check succeeded" << endl;
}
}
but it does not work i.e. it seems to think that the node_pri_msg[1] is non-empty, though there are no messages in any of the queues 'belonging' to it. Is there an easy way to do this?
I think you would be better served with this:
#include <iostream>
#include <queue>
#include <map>
using namespace std;
int main()
{
typedef std::queue<int> MessageQueue;
typedef std::map<int, MessageQueue> PriorityMap;
typedef std::map<int, PriorityMap> ClientMap;
ClientMap clients;
clients[10][1].push(1);
clients[10][1].push(2);
clients[11][2].push(3);
cout << boolalpha;
cout << clients[1].empty() << endl;
cout << clients[10].empty() << endl;
cout << clients[10][0].empty() << endl;
cout << clients[10][1].empty() << endl;
cout << clients[10][1].size() << endl;
return 0;
}
Output
true
false
true
false
2

a C++ hash map that preserves the order of insertion [duplicate]

This question already has answers here:
A std::map that keep track of the order of insertion?
(15 answers)
Closed 10 years ago.
I have the following code:
#include <iostream>
#include "boost/unordered_map.hpp"
using namespace std;
using namespace boost;
int main()
{
typedef unordered_map<int, int> Map;
typedef Map::const_iterator It;
Map m;
m[11] = 0;
m[0] = 1;
m[21] = 2;
for (It it (m.begin()); it!=m.end(); ++it)
cout << it->first << " " << it->second << endl;
return 0;
}
However, I am looking for something that preserves the order so that later I can iterate over the elements in the same order in which they were inserted. On my computer the above code does not preserve the order, and prints the following:
0 1
11 0
21 2
I thought maybe I could use a boost::multi_index_container
typedef multi_index_container<
int,
indexed_by<
hashed_unique<identity<int> >,
sequenced<>
>
> Map;
Can somebody show me how to implement my original code using this container (or any other appropriate container) so that the iterator follows the order of insertion?
#include <iostream>
#include "boost/unordered_map.hpp"
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
using namespace std;
using namespace boost;
using namespace boost::multi_index;
struct key_seq{};
struct key{};
struct Data_t
{
int key_;
int data_;
Data_t (int key_v, int data_v) : key_(key_v), data_(data_v) {}
};
int main()
{
typedef multi_index_container<
Data_t,
indexed_by<
hashed_unique<tag<key>, BOOST_MULTI_INDEX_MEMBER(Data_t,int,key_)>,
sequenced<tag<key_seq> >
>
> Map;
typedef Map::const_iterator It;
typedef index<Map,key>::type Map_hashed_by_key_index_t;
typedef index<Map,key>::type::const_iterator Map_hashed_by_key_iterator_t;
typedef index<Map,key_seq>::type Map_sequenced_by_key_index_t;
typedef index<Map,key_seq>::type::const_iterator Map_sequenced_by_key_iterator_t;
Map m;
m.insert(Data_t(11,0));
m.insert(Data_t(0,1));
m.insert(Data_t(21,1));
{
cout << "Hashed values\n";
Map_hashed_by_key_iterator_t i = get<key>(m).begin();
Map_hashed_by_key_iterator_t end = get<key>(m).end();
for (;i != end; ++i) {
cout << (*i).key_ << " " << (*i).data_ << endl;
}
}
{
cout << "Sequenced values\n";
Map_sequenced_by_key_iterator_t i = get<key_seq>(m).begin();
Map_sequenced_by_key_iterator_t end = get<key_seq>(m).end();
for (;i != end; ++i) {
cout << (*i).key_ << " " << (*i).data_ << endl;
}
}
return 0;
}
You can try creating an ordered map using the combination of map and the vector.
Vector can hold the pair of key and
value.
Vector iterator can be used as
iterator to traverse ordered map.
map can be used access the elements
faster.