Click here to Skip to main content
15,879,535 members
Articles / Programming Languages / C++
Article

Using the maps

Rate me:
Please Sign up or sign in to vote.
2.89/5 (9 votes)
23 Jan 20022 min read 136.2K   1.2K   25   13
The goal of this article is to demonstrate using one of the STL’s associative containers – the map.
Using the maps

Introduction

The goal of this article is to demonstrate using one of the STL’s associative containers – the map. The associative containers link a key with a value, allowing the value to be found given its key. The most powerful of the associative containers are map and multimap. These allow both the key and value to be of differing and arbitrary data types. The difference between map and multimap is that map requires unique keys and multimap does not.

Therefore, the map class supports an associative container in which unique keys are mapped with values. In essence, a key is simply a name that you give to a value. Once a value has been stored, you can retrieve it by using its key. Thus, in its most general sense a map is a list of key/value pairs. The power of a map is that you can look up a value given its key.

The template specification for map is shown here:

template <class Key, class T, class Comp = less<Key>, 
          class Allocator = allocator<T> class map

Here, Key is the data type of the keys, T is the data type of the values being stored (mapped), and Comp is a function that compares two keys.

The map class contains many useful functions, but I'll put priority on several the most important functions of this class, such as: insert, erase and find, which represents the strongest weapon of this associative container.

These functions are encapsulated inside MyCompanyEmployees class according to business requests.

The test application for this article refers to the system that is responsible for the simple management of employees in a company. This is only prototype, but it's enough to illustrate the power of the map class and its possible usages.

In my test application I use one modified class String Tokenizer too.

As illustration, I’m going to give one relatively simple example with the following class hierarchy:

class Employee
{
	// Some code
};

class Employees
{
  virtual bool InitData() = 0;

public:
  Employee employee;

  virtual bool AddToEmployees( Employee new_employee ) = 0;
  virtual bool RemoveFromEmployees( string ssn ) = 0;
  virtual bool FindEmployee( string ssn, Employee &employee_found ) = 0;
};

class MyCompanyEmployees : public Employees
{
  EmployeeMap theMap;
  EmployeeMap::iterator theIterator;

  bool InitData();

public:
  MyCompanyEmployees();
  ~MyCompanyEmployees();

  bool AddToEmployees( Employee new_employee );
  bool RemoveFromEmployees( string ssn );
  bool FindEmployee( string ssn, Employee &employee_found );
	STRING_VECTOR GetData( Employee employee );
};

// MyCompanyEmployees.cpp
#include <iostream>
#include <fstream>
#include "MyCompanyEmployees.h"
#include "StringTokenizer.h"

MyCompanyEmployees::MyCompanyEmployees()
{
  InitData();
}

MyCompanyEmployees::~MyCompanyEmployees()
{
}

bool MyCompanyEmployees::AddToEmployees( Employee new_employee )
{
  bool bRet;
  pair<map<string, Employee>::iterator, bool> result;

  result = theMap.insert( pair<string, Employee>( new_employee.GetSSN(), 
                          Employee( new_employee ) ) );
  if( result.second )
    bRet = true;
  else
    bRet = false;

  return bRet;
}

bool MyCompanyEmployees::RemoveFromEmployees( string ssn )
{
  bool bRes;
  int nResult;

  nResult = theMap.erase( ssn );
  if( nResult != 0 )
    bRes = true;
  else
    bRes = false;

  return bRes;
}

bool MyCompanyEmployees::FindEmployee( string ssn, Employee &employee_found )
{
  bool bRet;

  theIterator = theMap.find( ssn );
  if( theIterator != theMap.end() )
  {
    employee_found = theIterator->second;
    bRet = true;
  }
  else
    bRet = false;

  return bRet;
}

bool MyCompanyEmployees::InitData()
{
  bool bRet = true;
  char row[200];

  ifstream file( "parsing_file.txt", ios::in );
  if( !file )
  {
    cerr << "Error while file opening!";
    bRet = false;
    goto Exit;
  }

  while( !file.eof() )
  {
    file.getline( row, 200 );
    StringTokenizer strtok( row, "," );

    employee.SetSSN( strtok.elementAt( 0 ) );
    employee.SetFirstName( strtok.elementAt( 1 ) );
    employee.SetLastName( strtok.elementAt( 2 ) );
    employee.SetMaritalStatus( strtok.elementAt( 3 ) );
    employee.SetHomeAddress( strtok.elementAt( 4 ) );
    employee.SetHomePhoneNumber( strtok.elementAt( 5 ) );
    employee.SetOfficePhoneNumber( strtok.elementAt( 6 ) );
    employee.SetSalary( strtok.elementAt( 7 ) );
    employee.SetTitle( strtok.elementAt( 8 ) );
    theMap.insert( pair<string, Employee>( employee.GetSSN(), Employee(employee) ) );
  }

Exit:
  return bRet;
}

STRING_VECTOR MyCompanyEmployees::GetData( Employee employee )
{
  vector<string> str_vector;

  str_vector.push_back( employee.GetSSN() );
  str_vector.push_back( employee.GetFirstName() );
  str_vector.push_back( employee.GetLastName() );
  str_vector.push_back( employee.GetMaritalStatus() );
  str_vector.push_back( employee.GetHomeAddress() );
  str_vector.push_back( employee.GetHomePhoneNumber() );
  str_vector.push_back( employee.GetOfficePhoneNumber() );
  str_vector.push_back( employee.GetSalary() );
  str_vector.push_back( employee.GetTitle() );

  return str_vector;
}

This is pure C++ driver program and main function seems like this:

#include <iostream>
#include "MyCompanyEmployees.h"

typedef vector<string> STRING_VECTOR;

int main( void )
{
  string ssn;
  Employee emp;
  MyCompanyEmployees MyCompany;
  STRING_VECTOR employee_data;
  STRING_VECTOR::iterator employee_data_iterator;
  char input;

  cout << "DEMONSTRATION PROGRAM - EMPLOYEE" << endl;
  while( 1 )
  {
    cout << "Enter add(a), remove(r), find(f), quit(q): ";
    cin >> input;

    switch( input )
    {
    case 'a':
      {
        string ssn, first_name, last_name, marital_status, home_address, 
               home_phone_number, office_phone_number, salary, title;
        cout << endl << "Enter SSN: ";
        cin >> ssn;
        cout << "Enter first name: ";
        cin >> first_name;
        cout << "Enter last name: ";
        cin >> last_name;
        cout << "Enter marital status: ";
        cin >> marital_status;
        cout << "Enter home address: ";
        cin >> home_address;
        cout << "Enter home phone number: ";
        cin >> home_phone_number;
        cout << "Enter office phone number: ";
        cin >> office_phone_number;
        cout << "Enter salary: ";
        cin >> salary;
        cout << "Enter title: ";
        cin >> title;
        emp.SetSSN( ssn );
        emp.SetFirstName( first_name );
        emp.SetLastName( last_name );
        emp.SetMaritalStatus( marital_status );
        emp.SetHomeAddress( home_address );
        emp.SetHomePhoneNumber( home_phone_number );
        emp.SetOfficePhoneNumber( office_phone_number );
        emp.SetSalary( salary );
        emp.SetTitle( title );
        if( MyCompany.AddToEmployees( emp ) )
          cout << "Insertion occured...\n";
        else
          cout << "Duplicate not allowed...\n";
      }
      continue;
    case 'r':
      {
        cout << "Enter SSN that you want to remove: ";
        cin >> ssn;
        if( !MyCompany.RemoveFromEmployees( ssn ) )
          cout << "Error while removing..." << endl;
        else
          cout << "Removing occured..." << endl;
      }
      continue;
    case 'f':
      {
        cout << "Enter SSN that you want to find: ";
        cin >> ssn;
        if( MyCompany.FindEmployee( ssn, emp ) )
        {
          employee_data = MyCompany.GetData( emp );
          for( employee_data_iterator = employee_data.begin(); 
               employee_data_iterator != employee_data.end(); 
               employee_data_iterator++ )
          {
            cout << *employee_data_iterator;
            if( employee_data_iterator != employee_data.end() - 1 )
              cout << ", ";
          }
          cout << endl;
        }
        else
          cout << "Name not in directory...\n";
      }
      continue;
    case 'q':
      cout << "Quit\n";
      exit( 0 );
    default:
      cout << "Error: Bad command " << input << '\n';
      break;
    }
  }

  return 0;
}

Like a data source you have one simple text (parsing_file.txt) file which is filled with four lines of data:

1111,John,Johnson,yes,Street1,(416)111-1111,(416)101-1010,50000,Manager
2222,Adam,Smith,yes,Street2,(416)222-2222,(416)202-2020,35000,Technician
3333,Bob,Fitzgerald,no,Street3,(416)333-3333,(416)303-3030,45000,Programmer
4444,James,Sulivan,no,Street4,(416)444-4444,(416)404-4040,40000,Teacher

The first column represents, at the same time, the key in our map, so that if you want to find or remove some data from map you should type only the number: 1111 or 2222 or…

This example could be more useful because we have storing the class object in a map.

I recommend you one very helpful programmer's book that discuss STL topics - "STL programming from ground up", Herbert Schildt.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer student
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionproblem with erasing map elements Pin
psatyan26-May-06 9:42
psatyan26-May-06 9:42 
GeneralC++ Code for Time/Clock Pin
2-Mar-02 3:07
suss2-Mar-02 3:07 
GeneralRe: C++ Code for Time/Clock Pin
Christian Graus8-Dec-02 22:57
protectorChristian Graus8-Dec-02 22:57 
GeneralGood stuff in STL. Pin
Giles26-Jan-02 0:32
Giles26-Jan-02 0:32 
GeneralWhy not use CList Pin
Eric.Wang10-Jan-02 20:35
Eric.Wang10-Jan-02 20:35 
GeneralRe: Why not use CList Pin
Bill Leibold24-Jan-02 19:01
Bill Leibold24-Jan-02 19:01 
GeneralRe: Why not use CList Pin
mloibl27-Jan-02 21:28
mloibl27-Jan-02 21:28 
GeneralRe: Why not use CList Pin
Christian Graus27-Jan-02 21:38
protectorChristian Graus27-Jan-02 21:38 
1/ A list is just a list, a map offers an associative container. MFC offers them too.

2/ MFC containers are NOT powerful. I can write you a linked list that will work as well as CList in an afternoon, but if you wanted sort, or any other function, you'd need to write it yourself. STL comes with all these functions available to all the containers it provides.


Christian

I have come to clean zee pooollll. - Michael Martin Dec 30, 2001

Picture the daffodil. And while you do that, I'll be over here going through your stuff.

Picture a world without war, without hate. And I can picture us attacking that world, because they would never expect it.
Sonork ID 100.10002:MeanManOz
I live in Bob's HungOut now

GeneralRe: Why not use CList Pin
Simon Capewell27-Jan-02 23:04
Simon Capewell27-Jan-02 23:04 
GeneralRe: Why not use CList Pin
Christian Graus27-Jan-02 23:18
protectorChristian Graus27-Jan-02 23:18 
GeneralWhy not use CList Pin
Eric.Wang10-Jan-02 20:34
Eric.Wang10-Jan-02 20:34 
GeneralNice Pin
Nemanja Trifunovic8-Jan-02 10:00
Nemanja Trifunovic8-Jan-02 10:00 
GeneralSource code Pin
Mike Klimentiev7-Jan-02 7:52
Mike Klimentiev7-Jan-02 7:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.