unordered_map troubles.

I have a class called 'Graph' which has two unordered maps as private members. I add pairs to these maps and it seems to work fine. But when I try to use the maps inside of a certain function they return 0 for any key that is passed. And when I iterate through the map I see that there are many weird entries that are combinations of various keys I have used.
1
2
3
4
5
s >> v1 >> v2 >> weight;
v1 = v1.substr(0, v1.size()-1);
v2 = v2.substr(0, v2.size()-1);
cout << vMap[v1] << " " << vMap[v2] << endl;
addEdge(v1, v2, weight);

Here v1 and v2 are strings, and when I print out vMap[v1] and vMap[v2] they print the correct values. But the addEdge() function does not work properly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Graph::addEdge(string v1, string v2, int weight) {
	if(weight > 0) {
		if(eMap.find(v1.append(v2)) == eMap.end()) {
			Edge* e = new Edge({v1, v2, weight});
			edges.push_back(e);
			eMap[v1.append(v2)] = edgeCount;
			eMap[v2.append(v1)] = edgeCount;

			int first = vMap[v1];
			int second = vMap[v2];			
			
			matrix[first][second] = weight;
			matrix[second][first] = weight;

			edgeCount++;
		} else {
			int i = eMap[v1.append(v2)];
			edges[i]->weight = weight;	
		}
	}
}

Here the mapped value of vMap is always 0, I have no idea what is happening. This code was working perfectly earlier and I can't understand what I have done that has messed it up.
Last edited on
Be aware that operator[] as in myMap[myKey] has a double purpose in std::map and std::unordered_map:
1) if myKey doesn't exist, insert it with a value-initialized element (by using the default constructor if it's a class).
2) if myKey does exist, return the element associated with it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <ostream>
#include <string>
#include <unordered_map>

struct Element
{
    std::string s;

    Element(): s("SURPRISE!")
    {
    }

    Element & operator = (const std::string &rhs)
    {
        s = rhs;
        return *this;
    }
};

std::ostream & operator << (std::ostream &os, const Element &e)
{
    return os << e.s << '\n';
}

int main()
{
    std::unordered_map<int, Element> stuff;

    stuff[0] = "One";
    stuff[2] = "Three";

    std::cout << stuff[0] << stuff[1] << stuff[2] << std::endl;
}
One
SURPRISE!
Three


Thanks for the response. This is something I had considered, but even under a controlled input I am having problems. The map is fine and in the condition I would like until addEdge() is called. Once in this function any key which was valid is now mapped to 0.
1
2
3
4
5
			eMap[v1.append(v2)] = edgeCount;
			eMap[v2.append(v1)] = edgeCount;

			int first = vMap[v1];  // v1 = v1+v2 here
			int second = vMap[v2]; // v2 = v2 + v1	 

http://www.cplusplus.com/reference/string/string/append/
When you call std::string::append(), it changes the original string.
So maybe this is the problem, because you only wanted a temporary string instead?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void Graph::addEdge(string v1, string v2, int weight) {
	if(weight > 0) {
		if(eMap.find(v1.append(v2)) == eMap.end()) {
			Edge* e = new Edge({v1, v2, weight});
			edges.push_back(e);
			// eMap[v1.append(v2)] = edgeCount;
			// eMap[v2.append(v1)] = edgeCount;
			eMap[v1 + v2] = edgeCount;
			eMap[v2 + v1] = edgeCount;

			int first = vMap[v1];
			int second = vMap[v2];			
			
			matrix[first][second] = weight;
			matrix[second][first] = weight;

			edgeCount++;
		} else {
			// int i = eMap[v1.append(v2)];
			int i = eMap[v1 + v2];
			edges[i]->weight = weight;	
		}
	}
}


Ninja'd by norm b.
Thank you norm b and Catfish666. I just figured that out as I was working with my code and came back to post my findings only to see your answers.
Topic archived. No new replies allowed.