C++ Map with two keys of different values - c++

I need a map which can have two keys, of different data types, yet point to the same struct.
struct DataStruct {
SomeEnum keyEnum; // <---- key as enum
std::string keyString; // <----- a key as a string
int arbitrarydata;
int moredata;
}
Then I want a std::map I can look up like:
std::map<SomeEnum||std::string, DataStruct> dataMap;
dataMap[SomeEnum::AValue] = dataStruct1;
dataMap["mykey"] = dataStruct2;
Is this even possible or do I need to make 2 maps? Seems a waste. Or do I need to overload an operator or something?

You can use std::pair, like this:
#include <iostream>
#include <map>
#include <utility>
typedef enum {A, B, C} en;
int main ()
{
en myen = A;
std::map<std::pair<char,int>, int> mymap;
mymap.insert ( std::pair<std::pair<char, int>,int>(std::make_pair('a',myen),200) );
mymap.insert ( std::pair<std::pair<char, int>,int>(std::make_pair('z',30),400) );
// showing contents:
std::cout << "mymap contains:\n";
for (std::map<std::pair<char,int>, int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << "(" << it->first.first << ", " << it->first.second <<
") => " << it->second << '\n';
return 0;
}
Not an answer in the question:
Note, that in C++11, you can use enum class, which in general can be more useful.

A std::map can only have keys of the same type, but you can trick it with whatever key logic you want. Just be sure that they can compare properly:
struct DataStruct {
struct Key {
std::string keyString;
SomeEnum keyEnum;
int type;
Key(SomeEnum a) : keyEnum(a), type(0) { }
Key(const char * a) : keyString(a), type(1) { }
bool operator<(const Key & o) const {
if (type != o.type) return type < o.type;
else return type == 0 ? keyEnum < o.keyEnum : keyString < o.keyString;
}
};
int data;
}
Then you can use it almost the way you wanted:
std::map<DataStruct::Key, DataStruct> dataMap;
dataMap[SomeEnum::AValue] = dataStruct1;
dataMap["mykey"] = dataStruct2;
You need to be sure that keys of different types don't point to the same data, thats why I first order them by type and then by their value.

Related

Initialising a 2d map c++

I have been thinking lately about 2d structures (of integers) in which their sizes can grow dynamically. I came across 'map' which I think that it meets my following need: Essentially, what I want is to check whether a random entry has been initialized or not (do something if it has not been initialized yet).
int main(){
int int1, int2;
std::map<int,std::map<int,int>> my_map;
cout << "Enter two integers separated by space: ";
cin >> int1 >> int2;
if(has my_map[int1][int2] not been initialized){
do something
}
}
I am hoping that such functionality is available with C++.
If what you mean by checking whether an entry "has been initialized" is checking that a pair of keys has a value assigned to them -- one key for the outer map and one for the inner map -- you can test contents of a map of maps as below:
bool contains_keys(const std::map<int, std::map<int, int>>& map_of_maps, int key1, int key2) {
auto iter = map_of_maps.find(key1);
if (iter == map_of_maps.end()) {
return false;
}
return iter->second.find(key2) != iter->second.end();
}
However, I question whether a map of maps is really what you want. If what you want is just a mapping from two keys to a single value, a more direct and space efficient implementation is to use an std::map with an std::tuple or std::pair as the key type.
Tuples version below.
#include <map>
#include <tuple>
#include <iostream>
int main()
{
std::map<std::tuple<int, int>, int> map_of_pairs;
map_of_pairs[{42, 17}] = 3;
bool contains_42_17 = (map_of_pairs.find({ 42, 17 }) != map_of_pairs.end());
bool contains_67_23 = (map_of_pairs.find({ 67, 23 }) != map_of_pairs.end());
std::cout << ((contains_42_17) ? "yes\n" : "no\n");
std::cout << ((contains_67_23) ? "yes\n" : "no\n");
}
Also unless you actually need the above to be ordered, consider an unordered_map.
You could write a function that first checks the outer map for key1, then if an inner map exists with that key, check the inner map for key2.
bool nested_contains(std::map<int,std::map<int,int>> const& my_map, int key1, int key2)
{
auto itOuter = my_map.find(key1);
if (itOuter == my_map.end())
return false;
return itOuter->second.contains(key2);
}
Then use it like
int main()
{
int int1, int2;
std::map<int,std::map<int,int>> my_map;
std::cout << "Enter two integers separated by space: ";
std::cin >> int1 >> int2;
if(nested_contains(my_map, int1, int2)){
// do something
}
}
You can quickly do it creating a custom function using the find method.
In that case the algorithm is suitable for being generic.
template<typename T>
bool contains_keys_cpp_20(std::map<T, std::map<T, T>> const& nested_map, T key1, T key2)
{
auto pair = nested_map.find(key1);
return (pair != nested_map.end()) && (pair->second.contains(key2));
}
template<typename T>
bool contains_keys_cpp_17(std::map<T, std::map<T, T>> const& nested_map, T key1, T key2)
{
auto pair = nested_map.find(key1);
return (pair != nested_map.end()) && (pair->second.find(key2) != pair->second.end());
}
int main()
{
{
std::map<int, std::map<int, int>> my_map;
my_map[1] = { { 2, 1} };
bool result = contains_keys_cpp_17(my_map, 3, 2);
// false
}
{
std::map<int, std::map<int, int>> my_map;
my_map[3] = { { 2, 1} };
bool result = contains_keys_cpp_17(my_map, 3, 2);
// true
}
{
std::map<char, std::map<char, char>> my_map;
my_map['3'] = { { '2', '1'} };
bool result = contains_keys_cpp_17(my_map, '3', '2');
// true
}
return 0;
}

Generating a map of strings to std::list of pointers in c++

I am trying to achieve the creation of such a map. The following code attempts to do this
#include <list>
#include <map>
#include <string>
class IntWithString {
private:
int a;
std::string s;
public:
IntWithString(int a, std::string s) : a(a), s(s) {}
std::string getString() { return s; }
int getInt() { return a; }
};
namespace {
std::map<std::string, std::list<IntWithString *> > m;
}
void appendMap(IntWithString *a) {
auto it = m.find(a->getString());
if (it != m.end()) {
m[a->getString()].push_back(a);
} else {
std::list<IntWithString *> l;
l.push_back(a);
m[a->getString()] = l;
}
}
int main() {
IntWithString a(10, "ten");
IntWithString b(11, "ten");
appendMap(&a);
appendMap(&b);
return 0;
}
However when looking at the map m with the debugger I am getting a map that maps "ten" to a list of size 0. What I would like is a list of size 2.
I am not sure what you mean. If I do:
std::cout << m.size() << ", " << m["ten"].size() << std::endl;
I get this output:
1, 2
which is a map with one key ("ten"), and two values for that key (10 and 11), as expected.
Live demo
PS: Storing pointers in a container like this is a bit uncommon in C++. If you really want to do this though, consider to use Smart Pointers.

How to pass fields from a class to function in c++?

In some words: how can I pass various fields from a custom class to a single function?
Now in details:
I have a std::vector containing a class, for example CustomClass from which I have to extract a result from a field from this class by some criteria which are fields in this class and to combine somehow this data.
My first approach to this problem was to use a function which accepts as a parameter the std::vector of the class in order to extract the data and return a std:map. The key in this map is the type of the criteria by which the data should be combined and the value is an int with the combined data from all members of this vector.
The problem is that the criteria is not only one - more than one field from this class may be used as criteria (let for easiness all of the criteria are std::string, if they are not - I could make the function templated).
The easiest way for me now is to make dozens of functions with almost identical code and each of them to extract a simple concrete field from this class. However changes might require similar changes to all of the dozens of functions which would be a maintenance headache. But in this stage I cannot think how to pass to a single function a field from this class...
Here's an example code from this class:
// this is the class with data and criteria
class CustomClass
{
public:
std::string criteria1;
std::string criteria2;
std::string criteria3;
//... and others criteria
int dataToBeCombined;
// other code
};
// this is one of these functions
std::map<std::string, int> getDataByCriteria1(std::vector<CustomClass> aVector)
{
std::map<std::string, int> result;
foreach(CustomClass anObject in aVector)
{
if(result.find(anObject.criteria1)==result.end()) // if such of key doesn't exists
{
result.insert(std::make_pair(anObject.criteria1, anObject.dataToBeCombined));
}
else
{
// do some other stuff in order to combine data
}
}
return result;
}
and by similar way I should make the other functions which should work with CustomClass::criteria2, CustomClass::criteria3, etc.
I thought to make these criteria in a single array and to pass to this function only the number of the criteria but the class will be used by others for other purposes and the fields must be easy to read, so this will not be an option (i.e. the real names are not criteria1, criteria2, etc. but are descriptive).
Anyone with ideas?
EDIT: Someone referred my question to "C++ same function parameters with different return type" which obviously is very different - the function in my case return the same type every time, just the parameters it takes must be various fields from a class.
You can use pointer to member. Declare an argument std::string CustomClass::*pField in your function, pass it with &CustomClass::criteriaN, access it with anObject.*pField.
See more on the topic: Pointers to data members.
If all "criteria" are of the same type, I don't see an elegant solution but you can "enumerate" they in some way and use their number.
By example, you can declare a templated getVal() method in CustomClass in this way
template <int I>
const std::string & getVal () const;
and implement they, number by number, criteria by criteria, in this way (outside the body of the class)
template <>
const std::string & CustomClass::getVal<1> () const
{ return criteria1; }
template <>
const std::string & CustomClass::getVal<2> () const
{ return criteria2; }
template <>
const std::string & CustomClass::getVal<3> () const
{ return criteria3; }
Now, you can transform getDataByCriteria1() in a templated function getDataByCriteria() in this way
template <int I>
std::map<std::string, int> getDataByCriteria (std::vector<CustomClass> aVector)
{
std::map<std::string, int> result;
for (const auto & cc : aVector)
{
if ( result.find(cc.getVal<I>()) == result.end()) // if such of key doesn't exists
{
result.insert(std::make_pair(cc.getVal<I>(), cc.dataToBeCombined));
}
else
{
// do some other stuff in order to combine data
}
}
return result;
}
and call it in this way
auto map1 = getDataByCriteria<1>(ccVec);
auto map2 = getDataByCriteria<2>(ccVec);
auto map3 = getDataByCriteria<3>(ccVec);
--- EDIT: added solution (C++14 only) for different types criteria ---
A little different if the "criteria" are of different types.
The solution work but in C++14, thanks to auto and decltype().
By example, if
std::string criteria1;
int criteria2;
long criteria3;
You can declare getVal() with auto
template <int I>
const auto & getVal () const;
and define (with auto) all versions of getVal()
template <>
const auto & CustomClass::getVal<1> () const
{ return criteria1; }
template <>
const auto & CustomClass::getVal<2> () const
{ return criteria2; }
template <>
const auto & CustomClass::getVal<3> () const
{ return criteria3; }
and combining auto with decltype(), you can modify getDataByCriteria() in this way
template <int I>
auto getDataByCriteria (std::vector<CustomClass> aVector)
{
std::map<decltype(aVector[0].getVal<I>()), int> result;
for (const auto & cc : aVector)
{
if ( result.find(cc.getVal<I>()) == result.end()) // if such of key doesn't exists
{
result.insert(std::make_pair(cc.getVal<I>(), cc.dataToBeCombined));
}
else
{
// do some other stuff in order to combine data
}
}
return result;
}
The use of the function remain the same (thanks to auto again)
auto map1 = getDataByCriteria<1>(ccVec);
auto map2 = getDataByCriteria<2>(ccVec);
auto map3 = getDataByCriteria<3>(ccVec);
p.s.: caution: code not tested
p.s.2 : sorry for my bad English
You can use a function to extract a filed such as
std::string extractFiled(const CustomClass &object, int which) {
switch (which) {
case 1:
return object.criteria1;
case 2:
return object.criteria2;
case 3:
return object.criteria3;
default:
return object.criteria1;
}
}
and getDataByCriteria add an arg to indicate which filed to use.
Or you can just use macro to implement getDataByCriteria.
You tagged it C++11, so use variadic templates.
class VariadicTest
{
public:
VariadicTest()
{
std::map<std::string, int> test1 = getDataByCriteria(testValues, criteria1);
std::map<std::string, int> test2 = getDataByCriteria(testValues, criteria2);
std::map<std::string, int> test3 = getDataByCriteria(testValues, criteria1, criteria2);
std::map<std::string, int> test4 = getDataByCriteria(testValues, criteria1, criteria3);
}
private:
std::string criteria1 = { "Hello" };
std::string criteria2 = { "world" };
std::string criteria3 = { "." };
std::vector<CustomClass> testValues = { {"Hello",1}, {"world",2},{ "!",3 } };
template<typename T> std::map<std::string, int> getDataByCriteria(std::vector<CustomClass> values, T criteria)
{
std::map<std::string, int> result;
//do whatever is needed here to filter values
for (auto v : values)
{
if (v.identifier == criteria)
{
result[values[0].identifier] = values[0].value;
}
}
return result;
}
template<typename T, typename... Args> std::map<std::string, int> getDataByCriteria(std::vector<CustomClass> values, T firstCriteria, Args... args)
{
std::map<std::string, int> result = getDataByCriteria(values, firstCriteria);
std::map<std::string, int> trailer = getDataByCriteria(values, args...);
result.insert(trailer.begin(), trailer.end());
return result;
}
};
You do not specify the actual operations to be done under the various conditions of the criteria being met so it is hard to say how much they actually can be combined.
Here is a possible solution using the std::accumulate() of the STL along with some additional functionality. This example was compiled with Visual Studio 2015.
This approach would make sense if most of the functionality can be combined into a reasonably small accumulation function because most of the criteria are handled in the same way. Or you could have the accumulate_op() function call other functions for specific cases while handling the general case itself.
You might take this as a beginning and make the appropriate modifications.
One such modification may be to get rid of the use of std::map to maintain state. Since using this approach you would iterate through the std::vector doing the accumulation based on the criteria, I am not sure you would even need to use std::map to remember anything if you are accumulating as you go.
// map_fold.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <numeric>
// this is the class with data and criteria
class CustomClass
{
public:
CustomClass() : dataToBeCombined(0) {}
std::string criteria1;
std::string criteria2;
std::string criteria3;
//... and others criteria
int dataToBeCombined;
// other code
};
// This is the class that will contain the results as we accumulate across the
// vector of CustomClass items.
class Criteria_Result {
public:
Criteria_Result() : dataToBeCombined(0) {}
CustomClass myCriteria;
std::map<std::string, int> result1;
std::map<std::string, int> result2;
std::map<std::string, int> result3;
int dataToBeCombined;
};
// This is the accumulation function we provide to std::accumulate().
// This function will build our results.
class accumulate_op {
public:
Criteria_Result * operator ()(Criteria_Result * x, CustomClass &item);
};
Criteria_Result * accumulate_op::operator ()(Criteria_Result *result, CustomClass &item)
{
if (!result->myCriteria.criteria1.empty() && !item.criteria1.empty()) {
std::map<std::string, int>::iterator it1 = result->result1.find(item.criteria1);
if (it1 == result->result1.end()) // if such of key doesn't exists
{
result->result1.insert(std::make_pair(item.criteria1, item.dataToBeCombined));
}
else
{
// do some other stuff in order to combine data
it1->second += item.dataToBeCombined;
}
result->dataToBeCombined += item.dataToBeCombined;
}
if (!result->myCriteria.criteria2.empty() && !item.criteria2.empty()) {
std::map<std::string, int>::iterator it2 = result->result2.find(item.criteria2);
if (it2 == result->result2.end()) // if such of key doesn't exists
{
result->result2.insert(std::make_pair(item.criteria2, item.dataToBeCombined));
}
else
{
// do some other stuff in order to combine data
it2->second += item.dataToBeCombined;
}
result->dataToBeCombined += item.dataToBeCombined;
}
if (!result->myCriteria.criteria3.empty() && !item.criteria3.empty()) {
std::map<std::string, int>::iterator it3 = result->result3.find(item.criteria3);
if (it3 == result->result3.end()) // if such of key doesn't exists
{
result->result3.insert(std::make_pair(item.criteria3, item.dataToBeCombined));
}
else
{
// do some other stuff in order to combine data
it3->second += item.dataToBeCombined;
}
result->dataToBeCombined += item.dataToBeCombined;
}
return result;
}
int main()
{
Criteria_Result result;
std::vector<CustomClass> aVector;
// set up the criteria for the search
result.myCriteria.criteria1 = "string1";
result.myCriteria.criteria2 = "string2";
for (int i = 0; i < 10; i++) {
CustomClass xx;
xx.dataToBeCombined = i;
if (i % 2) {
xx.criteria1 = "string";
}
else {
xx.criteria1 = "string1";
}
if (i % 3) {
xx.criteria2 = "string";
}
else {
xx.criteria2 = "string2";
}
aVector.push_back (xx);
}
// fold the vector into our results.
std::accumulate (aVector.begin(), aVector.end(), &result, accumulate_op());
std::cout << "Total Data to be combined " << result.dataToBeCombined << std::endl;
std::cout << " result1 list " << std::endl;
for (auto jj : result.result1) {
std::cout << " " << jj.first << " " << jj.second << std::endl;
}
std::cout << " result2 list " << std::endl;
for (auto jj : result.result2) {
std::cout << " " << jj.first << " " << jj.second << std::endl;
}
std::cout << " result3 list " << std::endl;
for (auto jj : result.result3) {
std::cout << " " << jj.first << " " << jj.second << std::endl;
}
std::cout << " Trial two \n\n" << std::endl;
result.myCriteria.criteria2 = "";
result.result1.clear();
result.result2.clear();
result.result3.clear();
result.dataToBeCombined = 0;
// fold the vector into our results.
std::accumulate(aVector.begin(), aVector.end(), &result, accumulate_op());
std::cout << "Total Data to be combined " << result.dataToBeCombined << std::endl;
std::cout << " result1 list " << std::endl;
for (auto jj : result.result1) {
std::cout << " " << jj.first << " " << jj.second << std::endl;
}
std::cout << " result2 list " << std::endl;
for (auto jj : result.result2) {
std::cout << " " << jj.first << " " << jj.second << std::endl;
}
std::cout << " result3 list " << std::endl;
for (auto jj : result.result3) {
std::cout << " " << jj.first << " " << jj.second << std::endl;
}
return 0;
}
This produces the output as follows:
Total Data to be combined 90
result1 list
string 25
string1 20
result2 list
string 27
string2 18
result3 list
Trial two
Total Data to be combined 45
result1 list
string 25
string1 20
result2 list
result3 list

Map doesn't sort with regard to comparator c++

I'm trying to solve a issue where I'm inserting chars in to a map of type <char, int>. If the char already exists in the map I will increase the int by 1. I have created my own comparator for prioritizing the elements within the map. The priority doesn't work in the way I hope it would work since in the end the output doesn't follow the order.
#include <iostream>
#include <string>
#include <map>
#include <iterator>
using namespace std;
struct classcomp {
bool operator()(const int& a, const int& b) const {
return a < b;
}
};
bool isPresent(map<char,int,classcomp> mymap, char c){
return (mymap.find('b') != mymap.end());
}
int main(){
string input="dadbadddddddcabca";
map<char,int,classcomp> mymap;
char temp;
for(string::iterator it = input.begin(); it!=input.end(); ++it){
temp = *it;
if(!isPresent(mymap, temp))
mymap.insert(pair<char,int>(*it,1));
else
mymap[temp]++;
}
for (auto& x: mymap) {
cout << x.first << ": " << x.second << '\n';
}
return 0;
}
Gives the following output:
a: 4
b: 2
c: 2
d: 8
std::map is designed to be sorted by key, and providing comparator for type of value does not change anything. imagine you have std::map<char,char>, how would you think you can provide comparator for value (if it would be possible)?
So solution would be to use container that allows to sort by multiple keys like boost::multi_index or just create another map - reversed:
#include <iostream>
#include <string>
#include <map>
#include <iterator>
using namespace std;
int main(){
string input="dadbadddddddcabca";
map<char,int> mymap;
for(string::iterator it = input.begin(); it!=input.end(); ++it){
mymap[*it]++;
}
map<int,char> reversemap;
for (auto& x: mymap) {
reversemap.insert( make_pair( x.second, x.first ) );
}
for (auto& x: reversemap ) {
cout << x.first << ": " << x.second << '\n';
}
return 0;
}
Notice that your pre-check for element existance is completely redundant, std::map operator[] creates new element and initializes it, if it does not exists.
You may notice that in output you are missing some values now (though they are sorted), if that is not what you need, change reversemap type from map to multimap, which allows key duplicates.
The comparator is used to sort the chars and not the ints.
It is sorting the keys and seems to work just fine - a b c d.
map sorts its entries by key, not value. The char keys get silently cast to int in your classcomp::operator()
Why
mymap.find('b') != mymap.end());
and not
mymap.find(c) != mymap.end());
Maybe this is what you wanted
int main() {
std::string input="dadbadddddddcabca";
typedef std::map< char, int > map_t;
map_t mymap;
char temp;
for ( std::string::const_iterator it = input.begin(), e = input.end(); it != e; ++it ) {
temp = *it;
mymap[ temp ] = mymap[ temp ] + 1; // Hopufuly operator[] inserts zero initialized value, if can't find a key
}
typedef std::pair< typename map_t::key_type, typename map_t::mapped_type > pair_t;
std::vector< pair_t > sortedByValue;
sortedByValue.assign( mymap.begin(), mymap.end() );
std::sort( sortedByValue.begin(), sortedByValue.end(), []( const pair_t & left, const pair_t & right ) {
return left.second < right.second;
// change to
// return left.second > right.second;
// for descend order
} );
for ( const auto & x: sortedByValue ) {
std::cout << x.first << ": " << x.second << std::endl;
}
}
LWS link

Defining maps in class

I am new to C++ and am not able to correctly define maps in class definition.
Here is the code I have written:
#include<stdio.h>
#include <iostream>
#include <map>
#include <utility> // make_pair
#include <string.h>
#include <sstream>
using namespace std;
class assgnt
{
private:
//typedef std::map<int, int> MapType;
//MapType my_map;
public:
bool isGoodPoint(int x, int y);
void addGoodNeighbours(int x, int y);
};
inline bool assgnt::isGoodPoint(int x, int y)
{
string xs, ys;
stringstream xout, yout;
int xsum=0, ysum=0;
xout<<x; yout<<y;
xs = xout.str();
ys = yout.str();
for each (char c in xs)
{
xsum = xsum + int(c);
}
for each (char c in ys)
{
ysum = ysum + int(c);
}
if (xsum+ysum <= 19)
return true;
else
return false;
}
inline void assgnt::addGoodNeighbours(int x, int y)
{
//if assgnt::isGoodPoint(x+1,y)
if(isGoodPoint(x+1,y))
{
}
/*if isGoodPoint(x+1,y) and [x+1,y] not in points: points.append([x+1,y])
if isGoodPoint(x-1,y) and [x-1,y] not in points: points.append([x-1,y])
if isGoodPoint(x,y+1) and [x,y+1] not in points: points.append([x,y+1])
if isGoodPoint(x,y-1) and [x,y-1] not in points: points.append([x,y-1])*/
}
int main()
{
typedef std::map<int, int> MapType;
MapType my_map;
// insert elements using insert function
my_map.insert(std::pair<int, int>(0, 0));
int i=0;
while true
{
//my_map.insert(std::pair<int, int>(2, 2));
//my_map.insert(std::pair<int, int>(3, 3));
//my_map.insert(MapType::value_type(4, 4)); // all standard containers provide this typedef
//my_map.insert(std::make_pair(5, 5)); // can also use the utility function make_pair
MapType::iterator iter = my_map.begin();
std::cout << "Size of my_map: " << my_map.size() << '\n';
std::cout << "Enter a key to search for: ";
int c;
std::cin >> c;
iter = my_map.find(c);
if (iter != my_map.end())
{
int num = iter->second;
if(num == 0)
std::cout << "Value is found: " << iter->second << '\n';
else
std::cout << "Value not found: ";
}
else
std::cout << "Key is not in my_map" << '\n';
// my_map.clear();
}
I wish to define the map typedef std::map MapType; in the class definition, so that I can use it in all inline functions and the main() by creating its object.
Please help.
I suppose you want to use it outside of the class? Define it in a public section and be happy. Typedefs are absolutely safe from encapsulation point of view, they are just synonyms. Then you can use it in main as assgnt::MapType.
It looks like your compilation problems are not with your map, but your while syntax:
-while true
+while(true)
{
+}
To get your code to work, you need to fix a few problems:
Your class needs a public constructor
Make your map public.
When using your map outside the class, use the type assgnt::MapType
This will give you working code so you can try out whatever you're doing. I guess that's what your question was? That you could not get it working inside the class?
There are a few other errors in your code, but you should be able to figure those ones out ;)
Your while loop contains an error: it should be
while(true)
{
//...
}
Infinete loop is a bad idea (your program won't terminate) - you didn't coded any conditional statement like
while(true)
{
//...
if(some_condition)
break;
}
You need to make your my_map field public, so that you can access it from main (as well as the other procedures).
And finally instantiate your class:
int main()
{
assgnt obj;
//...
// now write obj.my_map instead of just my_map
}