1
std::map<char*, int> mymap; 
mymap['a'] = 1; 
mymap['b'] = 2;
mymap['c'] = 3;  

How to print 1, 2, 3 in that particular order if order of insertion gets changed? I don't know the insertion order . But the order of output should be same everytime.

Anirban Saha
  • 149
  • 9

2 Answers2

2

I don't know the insertion order . But the order of output should be same everytime.

This is exactly how std::map works. The iterators go through the element in the strict weak ordering induced by the comparator of the map. Insertion order does not affect the order of the iteration.

std::map<char*, int> How to print 1, 2, 3 in that particular order.

The problem here is that a map is ordered by the key rather than by value.

If you need to iterate over elements of a map in value-order, then it seems that you need a multi-index container. Such container can be looked up by one index, and iterated using another index. The C++ standard library does not provide such multi-index containers however.

The idea of multi-index container is quite simple. It consists of nodes just like a list or a tree does, but each node contains multiple sets of links - one for each index. A generic implementation of such container is not quite as simple as the idea is.

mymap['a'] = 1;

You cannot use a char as a lookup argument to a map whose key type is char*.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

This is probably what you need:

std::map<char, int> mymap; 
mymap.emplace(make_pair('a', 1)); 
mymap.emplace(make_pair('c', 3)); 
mymap.emplace(make_pair('b', 2)); 

for(auto& it : mymap)
    cout<<it.second<<endl;

map is sorted based on the keys not the values, If you need a variable size char then use string if char* is not optional use shared_ptr:

std::map<std::shared_ptr<char>, int> mymap; 
mymap.emplace(make_shared<char>(char('a')), 1); 

The main problem you have here is inserting a pointer as key means you always have unique key, for example two pointers point to different addresses in memory but the char stored in those addresses are the same which is not what you want from a map. if you wanted to keep it sorted based on the values just change the key and value.

sort map by value:

#include <iostream>
#include <memory>
#include <algorithm>
#include <map>
using namespace std;

template<typename A, typename B>
std::pair<B,A> flip_pair(const std::pair<A,B> &p)
{
    return std::pair<B,A>(p.second, p.first);
}

template<typename A, typename B>
std::multimap<B,A> flip_map(const std::map<A,B> &src)
{
    std::multimap<B,A> dst;
    std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), 
                   flip_pair<A,B>);
    return dst;
}

int main(void)
{
    std::map<std::shared_ptr<char>, int> mymap; 
    std::shared_ptr<char> a;
    a.reset(new char('a'));
    std::shared_ptr<char> b;
    b.reset(new char('b'));
    std::shared_ptr<char> c;
    c.reset(new char('c'));
    mymap.emplace(make_pair(a, 1)); 
    mymap.emplace(make_pair(c, 2)); 
    mymap.emplace(make_pair(b, 3)); 

    std::multimap<int, std::shared_ptr<char>> dst = flip_map(mymap);
    // dst is now sorted by what used to be the value in src!
    for(auto& it : dst)
       cout<<it.first<<endl;
}

credit of sorting map by value: https://stackoverflow.com/a/5056797/10933809

Oblivion
  • 7,176
  • 2
  • 14
  • 33
  • _"How to print 1, 2, 3 in that particular order if order of insertion gets changed?"_ Nope. There aren't any guarantees, regarding the order with `std::map`. – πάντα ῥεῖ Jun 15 '19 at 16:55
  • @πάνταῥεῖ yes there is no guarantee – Oblivion Jun 15 '19 at 16:56
  • Storing it as character or string is not an option. I have to store it as pointer only. – Anirban Saha Jun 15 '19 at 16:56
  • @AnirbanSaha I added an edit – Oblivion Jun 15 '19 at 17:00
  • @πάνταῥεῖ now the the order must be guaranteed – Oblivion Jun 15 '19 at 17:11
  • 1
    @AnirbanSaha *Storing it as character or string is not an option* -- Why? Who is giving these restrictions? Look at the hoops that have to be jumped through just because of this silly restriction. Also, the danger with the solution is that you now have pointers to local variables stored in the map, and as soon as those `char` variables go out of scope, the map has now invalid entries. – PaulMcKenzie Jun 15 '19 at 17:29
  • @PaulMcKenzie whoever wants to deal with pointers must take care of it's dangers. For now the refs are in the same scope as the char they refer to. I just don't understand why everybody want to start with pointers and omit what STL provides. – Oblivion Jun 15 '19 at 17:35
  • this is very, very terrible: `mymap.emplace(make_pair(&a, 1));` It also won't do what you think it will. – Radosław Cybulski Jun 15 '19 at 18:07
  • @RadosławCybulski he didn't clarify why he needs char* so I dumped one, that pointer is not related to the question. – Oblivion Jun 15 '19 at 18:12
  • He didn't, but by the way he asked question we can infere he is quite new to C / C++. And your code will lead him astray. – Radosław Cybulski Jun 15 '19 at 18:15
  • 1
    @oblivion I think they mean that you're supposed to use `mymap.emplace(&a, 1)`. – eerorika Jun 15 '19 at 18:16
  • 2
    What i mean is that it's bad idea to teach novice programmer, that he should take pointer to local variable. In fact this is bad idea pretty much always. Yes, the code is "correct" and compiler will run it just fine. It doesn't mean it's good think to teach others. – Radosław Cybulski Jun 15 '19 at 18:17