65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 map

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.89/5 (9投票s)

2002年1月5日

2分钟阅读

viewsIcon

138084

downloadIcon

1165

本文的目标是演示如何使用 STL 的关联容器之一——map。

使用 map

引言

本文的目标是演示如何使用 STL 的关联容器之一——map。关联容器将一个键与一个值关联起来,允许根据键找到对应的值。map 和 multimap 是关联容器中最强大的两个。它们允许键和值都具有不同且任意的数据类型。map 和 multimap 的区别在于,map 要求键是唯一的,而 multimap 则没有这个要求。

因此,map 类支持一个关联容器,其中唯一的键被映射到值。本质上,键只是您为值指定的一个名称。一旦值被存储,您就可以使用其键来检索它。因此,从最广泛的意义上讲,map 是一个键/值对的列表。map 的强大之处在于,您可以根据键查找值。

map 的模板规范如下所示

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

这里,Key 是键的数据类型,T 是存储(映射)的值的数据类型,Comp 是一个比较两个键的函数。

map 类包含许多有用的函数,但我会优先考虑这个类的一些最重要的函数,例如:insert、erase 和 find,它们代表了这个关联容器的最强武器。

这些函数根据业务需求封装在 MyCompanyEmployees 类中。

本文的测试应用程序指的是负责公司中员工简单管理的系统。这只是一个原型,但足以说明 map 类的强大功能及其可能的用途。

在我的测试应用程序中,我还使用了一个修改后的 String 类 Tokenizer

作为说明,我将给出一个相对简单的示例,包含以下类层次结构

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;
}

这是一个纯 C++ 驱动程序,主函数如下所示

#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;
}

作为数据源,您有一个简单的文本 (parsing_file.txt) 文件,其中包含四行数据

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

第一列同时代表 map 中的键,因此如果您想查找或删除 map 中的某些数据,您应该只输入数字:1111 或 2222 或…

这个例子更有用,因为我们正在 map 中存储类对象。

我推荐一本非常有帮助的程序员书籍,它讨论了 STL 主题——“从基础开始的 STL 编程”,Herbert Schildt。

© . All rights reserved.