• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 374
  • Last Modified:

Multiset member function to search common object attributes

Hi,

I have a multiset that is storing a user defined object. I wondered if there was a quick way to count the number of objects in the multiset that has a the same value stored for a particular attribute? i.e search for the number of objects in a mulitset of 200 objects that have the same 'name' attribute?

Thanks
0
simondopickup
Asked:
simondopickup
  • 13
  • 11
  • 5
1 Solution
 
evilrixSenior Software Engineer (Avast)Commented:
There is no built in way; however, you could iterate the multiset and create a map of attribute name as the key and count as the value and just add to the map (incrementing the value each time you find the attribute).
0
 
simondopickupAuthor Commented:
Well I am currently iterating through the multiset to display the aircraft_set (see below). I have ordered the set by name anyway. So, as iterator increments, I could store the name and count until the name changes- then creating a new insertion into my map.

What might that look like?
aircraft_iter=aircraft_set.begin();										// Display contents of the multiset
   while(aircraft_iter != aircraft_set.end())
	   (*aircraft_iter++).display();										// Use iterator to initiate the display function

Open in new window

0
 
Infinity08Commented:
How about the count_if algorithm ?

        http://www.cplusplus.com/reference/algorithm/count_if/
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
evilrixSenior Software Engineer (Avast)Commented:
>> How about the count_if algorithm ?
I thought about that but that counts anything that matches the predicate. In this case, as I understand it, the asker wants to sum up all the matching attribute names and I couldn't see how this would work with count_if.
0
 
Infinity08Commented:
>> and I couldn't see how this would work with count_if.

Using a function object, where you can set the name, would probaby solve that (assuming I understood the requirements).

But then again, the simple loop evilrix suggested might be more than sufficient.

For what it's worth :
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
 
struct Foo {
  std::string name;
  int value;
  Foo(const std::string &n, int v) : name(n), value(v) { }
  bool operator<(const Foo &f) const { return this->value < f.value; }
};
 
struct FooNameCompare {
  std::string name;
  FooNameCompare(const std::string &n) : name(n) { }
  bool operator()(const Foo &f) const { return f.name == this->name; }
};
 
int main(void) {
  std::multiset<Foo> mySet;
 
  mySet.insert(Foo("nameA", 1));
  mySet.insert(Foo("nameA", 2));
  mySet.insert(Foo("nameA", 3));
  mySet.insert(Foo("nameB", 4));
  mySet.insert(Foo("nameB", 5));
  mySet.insert(Foo("nameC", 6));
 
  std::cout << "nameA : " << count_if(mySet.begin(), mySet.end(), FooNameCompare("nameA")) << " times" << std::endl;
  std::cout << "nameB : " << count_if(mySet.begin(), mySet.end(), FooNameCompare("nameB")) << " times" << std::endl;
  std::cout << "nameC : " << count_if(mySet.begin(), mySet.end(), FooNameCompare("nameC")) << " times" << std::endl;
  
  return 0;
}

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Using a function object, where you can set the name
Yeah, I was working on the assumption that the name wasn't known up-front :)

Of course, if there is a definitive list of names that this would work... but the wording of the Q lead me to think this wouldn't be the case, hence I didn't suggest count_if.
0
 
Infinity08Commented:
>> Yeah, I was working on the assumption that the name wasn't known up-front :)

It doesn't need to be known - it can be set at run-time. See my example code.

But I repeat : this is possibly more complicated than it needs to be, and the simple loop you suggested should do the trick just fine.
0
 
simondopickupAuthor Commented:
I suppose the first thing i want to do is idnetify the number of unique name entries in the list and stick the unique name entries into an array. The loop the array using the values of the array as the argument to the count_if across the set??


#include <iostream>
#include <fstream>
#include <string>
#include <set>
using namespace std;
 
class aircraft
{
private:
	string model, callsign;
public:
	aircraft():model("Not assigned"),callsign("Not assigned")	// No argument constructor
	{}
	aircraft(string str1, string str2):model(str1),callsign(str2)// 
	{}
 
	friend bool operator<(const aircraft&, const aircraft&);	//Operator overload declarator
	friend bool operator==(const aircraft&, const aircraft&);	//Operator overload declarator
	aircraft operator = (const aircraft& a1)
	{
		string s1=a1.model;
		string s2=a1.callsign;
		return aircraft(s1,s2);									// Return by value of an initialised object	
	}
 
	void display()												// Display the values to the output
	{
		cout<<endl<<model<<"\t"<<callsign;
	}
 
	friend bool operator < (const aircraft& a1, const aircraft& a2)
	{
		if(a1.model==a2.model)
			return(a1.callsign<a2.callsign)?true:false;
		return (a1.model<a2.model)?true:false;
	}
	friend bool operator == (const aircraft& a1, const aircraft& a2)
	{
		return((a1.model==a2.model)&&(a1.callsign==a2.callsign))?true:false;
	}
	
};
 
 
int main()
{
   string firstWord="";														// Define a series of strings that will take extractions
   string secondWord="";													// from the traffic file.
   string thirdWord="";
   string fourthword="";
   string aircraft_type="";
   string call_sign="";
   string thisLine;
   std::ifstream traffic_file("TRAFFIC.DATA");								// ACE TRAFFIC FILE (System Input)
   multiset < aircraft, less<aircraft > >aircraft_set;						// Define an STL set called aircraft_set
   multiset<aircraft, less<aircraft> >::iterator aircraft_iter;				// Define an interator called aircraft_iter to the aircraft set
 
   if (!traffic_file)														// Check to ensure the file is opened correctly
   {
	   cout<<"\n Can't open TRAFFIC.data!"<<endl;
	   return 0;
   }
 
   
   
   getline(traffic_file, thisLine);											// Move the file pointer to the next line
   traffic_file >> firstWord >> secondWord >> thirdWord >> fourthword;
   call_sign=thirdWord;														// Assign call sign to thirdword (applicable to line2)
   aircraft_type=fourthword;												// Assign aicraft type to the fourth word (applicable to line 2)
   aircraft_set.insert(aircraft(aircraft_type,call_sign));					// Insert a new aircraft into the set
  
 
 
 
   int linecount=2;
   while(!(traffic_file.eof()))												// Loop while the file is within limits
   {
                getline(traffic_file, thisLine);							// Move the file pointer to the next line and get the string
                traffic_file >> firstWord >> secondWord >> thirdWord;		//Find the first 3 strings from the current file pointer
                linecount++;
                //cout<<firstWord<<" "<<secondWord<<" "<<thirdWord<<" "<<linecount<<" "<<endl;
                
 
                
           if ((call_sign!=secondWord)&&(thirdWord!=call_sign)) 			// If secondword is not callsign and third word is not callsign (changed)
                {
                   traffic_file >> fourthword;								// Move file pointer to the fourthword
                   call_sign=thirdWord;										// Assign call sign to thirdword
                   aircraft_type=fourthword;								// Assign aicraft type to the fourth word
				   aircraft_set.insert(aircraft(aircraft_type,call_sign));	// Insert a new aircraft into the set
                  
 
                }
   }
 
   aircraft_iter=aircraft_set.begin();										// Display contents of the multiset
   while(aircraft_iter != aircraft_set.end())
	   (*aircraft_iter++).display();										// Use iterator to initiate the display function
 
 
   //traffic_file.close();
   //re-open our file... easiest way to reset the file access
   //traffic_file.open("TRAFFIC.DATA");
   
 
   traffic_file.close();
   cout<<"\nNumber of aircraft is "<< aircraft_set.size()<<endl;
   return 0;

Open in new window

0
 
Infinity08Commented:
Maybe I misunderstood ...

Do you want to find the count for one specific given name ?
Or do you want to construct a kind of frequency table that gives all counts for all names in the multiset ?

In the latter case, ignore the count_if solution - it won't help you much.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> It doesn't need to be known - it can be set at run-time. See my example code.
No, I get that but even at runtime you need to know the names you are counting... your example has them hard coded.

  std::cout << "nameA : " << count_if(mySet.begin(), mySet.end(), FooNameCompare("nameA")) << " times" << std::endl;
  std::cout << "nameB : " << count_if(mySet.begin(), mySet.end(), FooNameCompare("nameB")) << " times" << std::endl;
  std::cout << "nameC : " << count_if(mySet.begin(), mySet.end(), FooNameCompare("nameC")) << " times" << std::endl;

Without knowing what you are counting you can't use count_if, right?

>> I suppose the first thing i want to do is idnetify the number of unique name entries in the list and stick the unique name entries into an array
But if you're gonna need to do this (as I suspected, hence I didn't suggest count_if) you might as well just count them as you go (like I first suggested) otherwise you have to find all unique names (1 pass) and then count each one (each count_if will require another pass). That's (if I am not mistaken) O(n^2) complexity. If you just do it as I suggested by iterating the multiset it has a complexity of Log(n) since it's all done as 1 pass.

0
 
evilrixSenior Software Engineer (Avast)Commented:
^^^ I*, please feel free to correct me if I mis-counted my complexities :)
0
 
simondopickupAuthor Commented:
Infinity08 - I want to the latter of the 2...

Evilrix ( i know I am making you work for this one). What might your initial idea look like? I have never used maps..
0
 
Infinity08Commented:
>> Without knowing what you are counting you can't use count_if, right?

Yes, that was where I misunderstood the requirement ;) I thought the count was for a given name, rather than for all names.

>> Infinity08 - I want to the latter of the 2...

go with evilrix's solution with the map then :) I'll leave you two to it heh :)
0
 
evilrixSenior Software Engineer (Avast)Commented:
Quick example.
#include <set>
#include <map>
#include <string>
#include <iostream>
 
struct foo
{
	foo(std::string s) : s(s){}
	std::string s;
 
	// Needed for the multiset
	bool operator < ( foo const & f ) const
	{
		return this->s < f.s;
	}
};
 
typedef std::multiset<foo> foo_multiset_t;
typedef std::map<std::string, int> count_map_t;
 
int main()
{
	foo_multiset_t foo_multiset;
	foo_multiset.insert(foo("apple"));
	foo_multiset.insert(foo("apple"));
	foo_multiset.insert(foo("apple"));
	foo_multiset.insert(foo("bannana"));
	foo_multiset.insert(foo("bannana"));
	foo_multiset.insert(foo("orange"));
 
	count_map_t count_map;
 
	for(foo_multiset_t::const_iterator setItr = foo_multiset.begin() ; setItr != foo_multiset.end() ; ++setItr)
	{
		count_map_t::iterator mapItr = count_map.find(setItr->s);
 
		if(mapItr != count_map.end())
		{
			++mapItr->second;
		}
		else
		{
			count_map[setItr->s] = 1;
		}
	}
 
	for(count_map_t::iterator mapItr = count_map.begin() ; mapItr != count_map.end() ; ++mapItr)
	{
		std::cout << mapItr->first << " = " << mapItr->second << std::endl;
	}
}

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
>> I have never used maps
Similar to a set, but they contain key/value and not just key.
The iterator is itr->first for the key and itr->second for the value.

http://www.cplusplus.com/reference/stl/map/
0
 
simondopickupAuthor Commented:

What does this do and why is my compiler not liking it? Suggesting i am missing syntax ';' ??!!!
count_map_t count_map;

I assume it is creating another map of type count_map_t.
0
 
evilrixSenior Software Engineer (Avast)Commented:
It's just creating a map... count_map_t is just a typedef for the map.
http://www.cprogramming.com/tutorial/typedef.html

You didn't miss out this line did you?
typedef std::map<std::string, int> count_map_t;
Line 18 & 19 in my example create these.
0
 
simondopickupAuthor Commented:
I am getting a conversion error on the line:
count_map_t::iterator mapItr = count_map.find(setItr->s);

in my programme, s is a string and a private member of a class. Which i have had to make public and dont like doing. Cant I make something I declare a friend of somesort in the object class so I dont have to do this.

I must admit, I am lost with this example. Lots of syntax I havent used before and so the solution you have dropped in, although sound, I am having difficulty translating to my problem. Just a novice thing!

I will drop in what i have so far so you can see the class definition and what i have so far.
#include <iostream>
#include <fstream>
#include <string>
#include <set>
#include <map>
using namespace std;
 
class aircraft
{
public:
	string model, callsign;
public:
	aircraft():model("Not assigned"),callsign("Not assigned")	// No argument constructor
	{}
	aircraft(string str1, string str2):model(str1),callsign(str2)// 
	{}
 
	friend bool operator<(const aircraft&, const aircraft&);	//Operator overload declarator
	friend bool operator==(const aircraft&, const aircraft&);	//Operator overload declarator
	aircraft operator = (const aircraft& a1)
	{
		string s1=a1.model;
		string s2=a1.callsign;
		return aircraft(s1,s2);									// Return by value of an initialised object	
	}
 
	void display()												// Display the values to the output
	{
		cout<<endl<<model<<"\t"<<callsign;
	}
 
	friend bool operator < (const aircraft& a1, const aircraft& a2)
	{
		if(a1.model==a2.model)
			return(a1.callsign<a2.callsign)?true:false;
		return (a1.model<a2.model)?true:false;
	}
	friend bool operator == (const aircraft& a1, const aircraft& a2)
	{
		return((a1.model==a2.model)&&(a1.callsign==a2.callsign))?true:false;
	}
		
};
 
int main()
{
   string firstWord="";														// Define a series of strings that will take extractions
   string secondWord="";													// from the traffic file.
   string thirdWord="";
   string fourthword="";
   string aircraft_type="";
   string call_sign="";
   string thisLine;
   std::ifstream traffic_file("TRAFFIC.DATA");								// ACE TRAFFIC FILE (System Input)
   typedef multiset < aircraft, less<aircraft > >aircraft_set;				// Define an STL set called aircraft_set
   aircraft_set::const_iterator aircraft_iter;								// Define an interator called aircraft_iter to the aircraft set
   typedef map<aircraft,int>ac_map;											// Declare a type definition for the aircraft map
   ac_map::iterator ac_map_iter;											// Declare the iterator for the map
   ac_map count_map;														// Define a map called count_map
   aircraft_set ac_set;														// Define an aircraft set called ac_set
  
 
   if (!traffic_file)														// Check to ensure the file is opened correctly
   {
	   cout<<"\n Can't open TRAFFIC.data!"<<endl;
	   return 0;
   }
 
   
   
   getline(traffic_file, thisLine);											// Move the file pointer to the next line
   traffic_file >> firstWord >> secondWord >> thirdWord >> fourthword;
   call_sign=thirdWord;														// Assign call sign to thirdword (applicable to line2)
   aircraft_type=fourthword;												// Assign aicraft type to the fourth word (applicable to line 2)
   ac_set.insert(aircraft(aircraft_type,call_sign));					// Insert a new aircraft into the set
   				
	
 
  
 
 
 
   int linecount=2;
   while(!(traffic_file.eof()))												// Loop while the file is within limits
   {
                getline(traffic_file, thisLine);							// Move the file pointer to the next line and get the string
                traffic_file >> firstWord >> secondWord >> thirdWord;		//Find the first 3 strings from the current file pointer
                linecount++;
                //cout<<firstWord<<" "<<secondWord<<" "<<thirdWord<<" "<<linecount<<" "<<endl;
                
 
                
           if ((call_sign!=secondWord)&&(thirdWord!=call_sign)) 			// If secondword is not callsign and third word is not callsign (changed)
                {
                   traffic_file >> fourthword;								// Move file pointer to the fourthword
                   call_sign=thirdWord;										// Assign call sign to thirdword
                   aircraft_type=fourthword;								// Assign aicraft type to the fourth word
				   ac_set.insert(aircraft(aircraft_type,call_sign));		// Insert a new aircraft into the set
                  
 
                }
   }
 
 
   for (aircraft_iter=ac_set.begin();aircraft_iter!=ac_set.end();++aircraft_iter)
   {
	   ac_map_iter=count_map.find(aircraft_iter->model);					// Pointer to the model attribute
 
	   if (ac_map_iter != count_map.end())
	   {
		   ++ac_map_iter->second;
	   }
	   else
	   {
		   ac_map_iter[aircraft_iter->model] = 1;
	   }
   }
 
   for (ac_map_iter=count_map.begin();ac_map_iter != count_map.end();++ac_map_inter)
   {
	   std::cout << ac_map_iter->first << " = " << ac_map_iter->second << std::endl;
   }

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
>> in my programme, s is a string and a private member of a class. Which i have had to make public and dont like doing

You dont' need to -- I just made it public for simplicity. Leave it private and make an accessor

std::string const & MyClass::GetString() const { return s; }
std::string const & s = myClass.GetString();

>> I must admit, I am lost with this example. Lots of syntax I havent used before and so the solution you have dropped in, although sound, I am having difficulty translating to my problem. Just a novice thing!
Step through it with the debugger... it's not that complex and I'm sure if you do that it'll make more sense.
0
 
simondopickupAuthor Commented:
Okay,

What does this bit do in words please...I will award points then. Thank you
if(mapItr != count_map.end())
		{
			++mapItr->second;
		}
		else
		{
			count_map[setItr->s] = 1;
		}

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
:) ok when I get home I'll annotated the code and repost it
0
 
simondopickupAuthor Commented:
string const & getmodel() const
      {return model;}

 ac_map_iter=count_map.find(aircraft_iter->getmodel());

The compiler is dropping out here? Trying to solve the issue of accessing a private attribute 'model' in the class. Then the code is about to run into the bit that I have just asked to be annotated from you.

The error it drops out here is:

error C2664: 'std::_Tree<_Traits>::iterator std::_Tree<_Traits>::find(const aircraft &)' : cannot convert parameter 1 from 'const std::string' to 'const aircraft &'            
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> rror C2664: 'std::_Tree<_Traits>::iterator std::_Tree<_Traits>::find(const aircraft &)' : cannot convert parameter 1 from 'const std::string' to 'const aircraft &'

It seems you have declared the map as std::map<aircraft, int> when it should be std::map<string, int> assuming the attributes you are using for the keys are strings... I chose string as an example.

Ok, basically, all we're doing is iterating through all the objects in your multi-set and for each model we are doing in lookup in a map (think of a map as an array but rather than using numbers to index it we're using the model name) and if we don't find it in the map we're adding it and setting the count to one but if we do find it in the map we just increment the count by one. At the end, once we've passed through the whole set the map will contain one entry for every model, the key being the model and and the value being the number of times we found it in the multi-set.

Same code as above, but with annotations, modified to me more "aircraft" like and with the GetModel() accessor added....
#include <set>
#include <map>
#include <string>
#include <iostream>
 
//RX: This is a representation of your aircraft class
class aircraft
{
public:
	aircraft(std::string sModel) : m_sModel(sModel){}
 
	// Needed for the multiset
	bool operator < ( aircraft const & rhs ) const
	{
		return m_sModel < rhs.m_sModel;
	}
 
	std::string const & GetModel() const { return m_sModel; }
 
private:
	std::string m_sModel;
};
 
typedef std::multiset<aircraft> aircraft_multiset_t;
typedef std::map<std::string, int> count_map_t;
 
int main()
{
	// Set up some test data
	aircraft_multiset_t aircraft_multiset;
	aircraft_multiset.insert(aircraft("harrier"));
	aircraft_multiset.insert(aircraft("harrier"));
	aircraft_multiset.insert(aircraft("harrier"));
	aircraft_multiset.insert(aircraft("boeing"));
	aircraft_multiset.insert(aircraft("boeing"));
	aircraft_multiset.insert(aircraft("airbus"));
 
	// Create a map to keep track of the count of models
	count_map_t count_map;
 
	// Iterate through every item in the multi-set
	for(aircraft_multiset_t::const_iterator setItr = aircraft_multiset.begin() ; setItr != aircraft_multiset.end() ; ++setItr)
	{
		// See if we can find current model in the map
		count_map_t::iterator mapItr = count_map.find(setItr->GetModel());
 
		// Did we find it?
		if(mapItr != count_map.end())
		{
			// Found it, increment the count
			++mapItr->second;
		}
		else
		{
			// Not found, so add it with a start count of 1 (cos we've just found 1)
			count_map[setItr->GetModel()] = 1;
		}
	}
 
	// Now iterate through the map we built and just output to console to show it worked as expect
	for(count_map_t::iterator mapItr = count_map.begin() ; mapItr != count_map.end() ; ++mapItr)
	{
		std::cout << mapItr->first << " = " << mapItr->second << std::endl;
	}
}

Open in new window

0
 
simondopickupAuthor Commented:
OKay I have had it.

I am hoping someone will look at the CODE i have attached and answer a couple of questions for me:

1)  Why the error on line 103:
ac_map_iter=count_map.find(aircraft_iter->getmodel());
I have built an accessor to the private model attribute.
2) Please explain the following syntax and what it does in runtime. I am assuming 'second' is an object function of some STL class?

if (ac_map_iter != count_map.end())
         {
               ++ac_map_iter->second;
         }
         else
         {
               ac_map_iter[aircraft_iter->getmodel()] = 1;
         }

I am desperate to close this question and achieve this 'simple' counter using the maps!!!!

Many thanks, hopefuly for the last time today....:P

Simondo



#include <iostream>
#include <fstream>
#include <string>
#include <set>
#include <map>
using namespace std;
 
class aircraft
{
private:
	string model, callsign;
public:
	aircraft():model("Not assigned"),callsign("Not assigned")	// No argument constructor
	{}
	aircraft(string str1, string str2):model(str1),callsign(str2)// 
	{}
 
	friend bool operator<(const aircraft&, const aircraft&);	// Operator overload declarator
	friend bool operator==(const aircraft&, const aircraft&);	// Operator overload declarator
	aircraft operator = (const aircraft& a1)
	{
		string s1=a1.model;
		string s2=a1.callsign;
		return aircraft(s1,s2);									// Return by value of an initialised object	
	}
 
	void display()												// Display the values to the output
	{
		cout<<endl<<model<<"\t"<<callsign;
	}
 
	friend bool operator < (const aircraft& a1, const aircraft& a2)
	{
		if(a1.model==a2.model)
			return(a1.callsign<a2.callsign)?true:false;
		return (a1.model<a2.model)?true:false;
	}
	friend bool operator == (const aircraft& a1, const aircraft& a2)
	{
		return((a1.model==a2.model)&&(a1.callsign==a2.callsign))?true:false;
	}
	string const & getmodel() const								// An accessor for the private member model
	{return model;}
		
};
 
 
int main()
{
   string firstWord="";														// Define a series of strings that will take extractions
   string secondWord="";													// from the traffic file.
   string thirdWord="";
   string fourthword="";
   string aircraft_type="";
   string call_sign="";
   string thisLine;
   std::ifstream traffic_file("TRAFFIC.DATA");								// ACE TRAFFIC FILE (System Input)
   typedef multiset <aircraft, less<aircraft> >aircraft_set;				// Define an STL set called aircraft_set
   typedef map<aircraft,int>ac_map;											// Declare a type definition for the aircraft map
   aircraft_set::const_iterator aircraft_iter;								// Define an interator called aircraft_iter to the aircraft set
   ac_map::iterator ac_map_iter;											// Declare the iterator for the map
   ac_map count_map;														// Define a map called count_map
   aircraft_set ac_set;														// Define an aircraft set called ac_set
 
  
 
   if (!traffic_file)														// Check to ensure the file is opened correctly
   {
	   cout<<"\n Can't open TRAFFIC.data!"<<endl;
	   return 0;
   }
 
   getline(traffic_file, thisLine);											// Move the file pointer to the next line
   traffic_file >> firstWord >> secondWord >> thirdWord >> fourthword;
   call_sign=thirdWord;														// Assign call sign to thirdword (applicable to line2)
   aircraft_type=fourthword;												// Assign aicraft type to the fourth word (applicable to line 2)
   ac_set.insert(aircraft(aircraft_type,call_sign));						// Insert a new aircraft into the set
   				
   int linecount=2;
   while(!(traffic_file.eof()))												// Loop while the file is within limits
   {
                getline(traffic_file, thisLine);							// Move the file pointer to the next line and get the string
                traffic_file >> firstWord >> secondWord >> thirdWord;		// Find the first 3 strings from the current file pointer
                linecount++;
                //cout<<firstWord<<" "<<secondWord<<" "<<thirdWord<<" "<<linecount<<" "<<endl;
                
 
                
           if ((call_sign!=secondWord)&&(thirdWord!=call_sign)) 			// If secondword is not callsign and third word is not callsign (changed)
                {
                   traffic_file >> fourthword;								// Move file pointer to the fourthword
                   call_sign=thirdWord;										// Assign call sign to thirdword
                   aircraft_type=fourthword;								// Assign aicraft type to the fourth word
				   ac_set.insert(aircraft(aircraft_type,call_sign));		// Insert a new aircraft into the set
           
                }
   }
 
	
 
   for (aircraft_iter=ac_set.begin();aircraft_iter!=ac_set.end();++aircraft_iter)
   {
	   ac_map_iter=count_map.find(aircraft_iter->getmodel());				
 
	   if (ac_map_iter != count_map.end())
	   {
		   ++ac_map_iter->second;
	   }
	   else
	   {
		   ac_map_iter[aircraft_iter->getmodel()] = 1;
	   }
   }
 
   for (ac_map_iter=count_map.begin();ac_map_iter != count_map.end();++ac_map_inter)
   {
	   std::cout << ac_map_iter->first << " = " << ac_map_iter->second << std::endl;
   }
 
   aircraft_iter=ac_set.begin();											// Display contents of the multiset
   while(aircraft_iter != ac_set.end())
	   (*aircraft_iter++).display();										// Use iterator to initiate the display function
 
   //traffic_file.close();
   //re-open our file... easiest way to reset the file access
   //traffic_file.open("TRAFFIC.DATA");
   
   traffic_file.close();
   cout<<"\nNumber of aircraft is "<< ac_set.size()<<endl;
   return 0;
}

Open in new window

0
 
simondopickupAuthor Commented:
Here is the file that goes with....(TRAFFIC.data)!
aircraft.txt
0
 
evilrixSenior Software Engineer (Avast)Commented:
1. I've already answered this for you, look above.

typedef map<aircraft,int>ac_map;      is incorrect
typedef map<std::string,int>ac_map; is what you want

2. Again, answered above...

It is looking into the map to see if it can find the model, if not it addes it with a count of 1 else it just increments the count of the exiting model. itr->first is the key (model) and itr->second is the value (the count)... again I also explained this above :)

>> I am desperate to close this question and achieve this 'simple' counter using the maps!!!!
I'm trying to answer as fast as I can but I also have a daytime job and since that pays me it has to take priority I'm afraid :)
0
 
simondopickupAuthor Commented:
Okay evilrix thanks for all your help. I didnt see your post above and you have now sorted it.

Thanks very much. It is clear I have buckets of learning to do - but doing things a little more out of my comfort zone usually helps with this. Thanks for all your help.

I am in the middle of a big C++ project at the minute so you will be hearing more from me....yaaawwwnn..

Thanks again!!!!!

Simondo
0
 
simondopickupAuthor Commented:
Excellent! Thanks
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Okay evilrix thanks for all your help. I didnt see your post above and you have now sorted it.
No sweat, easy to miss when there ar elots of posts going on :)

>> It is clear I have buckets of learning to do
We all started in the same place.. the more you do the better you get

>> I am in the middle of a big C++ project at the minute so you will be hearing more from me....yaaawwwnn..
Muhahaha... I look forward to helping you again
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 13
  • 11
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now