using std::maps

May 6, 2011 at 4:47pm
I've been trying to get my head around maps having never used them before but I'm confused at to how they work. I have a map that stores a string, a start time and an end time, so that you can call start or stop repeatedly on my timer class with a certain name for that timer, and it will keep track of the total time that has passed for the timer with that name

I have a vector of maps

std::vector<std::map<std::string, long, long>> m_timers;

the first item in the map is the timer name, the second is to store the time when StartTimer() was called, and the last item will accumulate a total amount of time passed for this timer.

I want to say in the StartTimer() function something equivalent to "if a timer with this given name exists, set the start time, otherwise add a new element to the map."

and in the StopTimer() function, something equivalent to "if the timer exists, add the amount of time that has passed onto the accumulated time."

The problem I'm having is actually getting at the items in the map, since they're stored in a vector, I can't use std::find on them....very confused >:(

Thanks.
Last edited on May 6, 2011 at 4:48pm
May 6, 2011 at 4:51pm
Why do you have a vector of maps? You can store more than one set of data in a map. I think your constructor for the map is wrong; in my reference, the acceptable constructors are

map<key, elem>

and

map <key, elem, sortingOperation>

If you want to store more than one piece of data per key, use a structure.

Just have a single map container. Something like

1
2
3
4
5
6
7
struct times
{
  long startTime;
  long finishTime;
};

std::map<std::string, times>  m_timers;
Last edited on May 6, 2011 at 4:57pm
May 6, 2011 at 4:52pm
Maps associate a key with a value (2 things). You can make the second value a type that holds two things, however.

I recommend reading up on maps first:
http://cplusplus.com/reference/stl/map/

Now, my next suggestion is to just store the time it started. You can do the math with the current time to get the elapsed time.

You might be interested in this thread:
http://www.cplusplus.com/forum/beginner/23636/
May 6, 2011 at 4:54pm
A few things:

1) The 3rd template param for map is not what you seem to think. If you want the map to have multiple values for data, you'll need to put those values in a struct:

1
2
3
4
5
6
7
8
9
10
struct Timer
{
  std::string name;
  long starttime;
  long totaltime;
}

//...

std::map< std::string, Timer > m_timers;


2) Why do you have a vector here? Why not just use a single map? Do you have several different groups of timers that you need to keep separate?
May 6, 2011 at 5:24pm
thanks guys I had completely the wrong idea I thought one map was just one set of associated data. I now have this

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
void CProfiler::StartTimer(std::string timerName)
{
	std::map<std::string,timerInfo>::iterator it = m_timers.find(timerName);
	if ( it == m_timers.end() ) // if the name cannot be found in the map
	{
		m_timers.insert(std::pair<std::string,timerInfo>(timerName, timerInfo(GetTime(),0)));
	}
	else
	{
		it->second.startTime = GetTime();
	}

	std::cout << "starting timer: " << timerName << " - total time is " << it->second.totalTime << "\n";
}

void CProfiler::StopTimer(std::string timerName)
{
	std::map<std::string,timerInfo>::iterator it = m_timers.find(timerName);
	if ( it != m_timers.end() )
	{
		it->second.totalTime += GetTime() - it->second.startTime;
		std::cout << timerName << " total is " << it->second.totalTime << "\n";
	}

	std::cout << "stopping timer: " << timerName << " - total time is " << it->second.totalTime << "\n";
}


but the only error I get is an unresolved external

Error 3 error LNK2001: unresolved external symbol "private: static class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct timerInfo,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,struct timerInfo> > > CProfiler::m_timers" (?m_timers@CProfiler@@0V?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@UtimerInfo@@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@UtimerInfo@@@std@@@2@@std@@A) C:\Users\g7006454\Desktop\AGS (5th May)(new)\milestones 2-4\milestone 2-4 code\Win32_SDL\Profiler.obj Win32_SDL

EDIT - Also, what is the purpose of the third parameter in a map?
Last edited on May 6, 2011 at 5:26pm
May 6, 2011 at 5:27pm
Where is m_timers defined?
May 6, 2011 at 5:31pm
in CProfiler.h

static std::map<std::string, timerInfo> m_timers;

EDIT - and here's timerInfo

1
2
3
4
5
6
struct timerInfo{
	timerInfo() : startTime(0), totalTime(0) {}
	timerInfo(long s, long t) : startTime(s), totalTime(t) {}
	long startTime;
	long totalTime;
};


SILLY ME - m_timers is static and I hadn't declared it in the .cpp file
Last edited on May 6, 2011 at 5:36pm
May 6, 2011 at 5:37pm
If it's static, you need to instantiate it.

Put this in one and only one cpp file (probably in CProfiler.cpp)
std::map<std::string, timerInfo> CProfiler::m_timers;

Also, what is the purpose of the third parameter in a map?


It allows you to specify a custom way to compare objects:

http://cplusplus.com/reference/stl/map/
May 6, 2011 at 5:56pm
Great responses buys thanks a bunch really.

One last thing, when I print out the time in StartTimer(), if it is a new timer the time is printed as some garbage value like -41837251928, but when i stop the timer the time is correct every time, and upon starting a timer the second or third or any other time the time is printed correctly too.
Last edited on May 6, 2011 at 5:56pm
May 6, 2011 at 6:32pm
That's because it is a bad iterator when you try to print it in StartTimer (remember if the timer is new, then it == m_timers.end(), so it's bad!)

to correct it, assign it to the iterator that insert returns:

 
it = m_timers.insert(std::pair<std::string,timerInfo>(timerName, timerInfo(GetTime(),0))).second;

Topic archived. No new replies allowed.