Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43655
  • 博文数量: 15
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 176
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-31 01:57
个人简介

资深码农

文章分类

全部博文(15)

文章存档

2016年(3)

2014年(12)

我的朋友

分类: C/C++

2014-02-08 21:52:23

C++编程思想第二卷第六章讲解了STL算法相关的知识,学习了之后找来课后练习题6-33,原题是这样描述的,“编写一个程序,给定一个姓氏,找出每个有这样姓氏的人以及他或她的电话号码。使用处理序列范围的算法(例如upper_bound、lower_bound、equal_range等等,以姓氏作为主关键字,名字作为次关键字进行排序。假定从形式如下的文件中读入姓名及电话号码。
John Doe 3459483
Nick Bonham 3492930
Jane Doe 2832819

这里用数组代替文件进行输入。看到这样的问题,思路是使用STL的MAP容器进行储存,原题说使用姓氏作为关键字,那我们不妨定义一个类Name储存姓氏信息,

点击(此处)折叠或打开

  1. class Name {
  2. private:
  3.     string familyName;
  4.     string givenName;
  5. public:
  6.     Name(string FName = "", string GName = "") :
  7.             familyName(FName), givenName(GName) {
  8.     }
  9.     virtual ~Name() {
  10.     }
  11.     const string& getFamilyName() const {
  12.         return familyName;
  13.     }
  14.     const string& getGivenName() const {
  15.         return givenName;
  16.     }
  17. }
其中有family name 和given name两个string类型的成员变量,分别用来存储姓氏和名字。而使用Name作为容器MAP的key我们还需要做一个很重要的事情,那就是重载运算符"<",而且这个方法中一定不能写错,必须保证如果给定两个对象A跟B,如果有A < B为TRUE,则B < A一定为FALSE。重载代码如下,

点击(此处)折叠或打开

  1. bool operator <(const Name & rhs) const {
  2.         if (familyName < rhs.familyName) {
  3.             return true;
  4.         } else if (familyName == rhs.familyName) {
  5.             if (givenName < rhs.givenName)
  6.                 return true;
  7.         }
  8.         return false;
  9.     }
遵循题目要求使用family name作为主关键字,我们首先比对family name,如果其相等再比对given name,注意这里方法的实现。

下面我们要考虑如何定义一个数据结构来表示人名和电话号码,我们考虑使用一个二维数组,方便起见对姓氏,名字以及电话号码都是用string类型进行表示,
 string NameArray[][3] =
 {{"John", "Doe",    "3459483" },
  { "Nick", "Bonham", "3492930" },
  { "Jane", "Doe",    "2832819" },
  { "Adam", "Clark",  "6518324" },
  { "Judy", "Foast",  "9821572" },
  { "Zeus", "Lenos",  "4552341" },
  { "Cole", "Minas",  "1351244" },
  { "Ooos", "Clark",  "1562553" } };
有了这些输入,我们就可以把它们读入到MAP容器中,进行操作,MAP容器的定义如下,
map infoMap;
往map中插入成员需要用到pair类型,这也不难理解,因为map中的元素都是成对出现的,因此插入的形式就是这样,
infoMap.insert(pair(name, number));
下面就是最后一步,查找。
使用键盘进行输入,从控制台可以输入一个姓氏,可以使用std::cin,代码像这样cin >> FamilyName。
输入之后首先要把输入的姓氏转化成一个完整的姓名,然后才能进行查找,由于我们之前定义的Name类的构造函数使用了默认空字符串作为默认参数,这样我们就可以直接用键盘输入的姓氏构造一个待查找的键值key,
  string aFmlyName;
  cin >> aFmlyName;
  Name inputName(aFmlyName);
这样如果从键盘输入Bush,则会构造一个完整的Name("Bush", "")对象。
接下来进行查找,我们使用map容器提供的lower_bound方法(其实还有一个通用的lower_bound方法,不过map本身自带的效率更高),lower_bound方法返回一个iterator,这个iterator指向[first, end)的有序序列之中第一个可以插入value而不破坏原有容器顺序的位置。
而本身map中的各个元素都是经过排序的(排序过后同样姓氏的人会集中在一起,比如Lucas Hill 和 Mat Hill 会一前一后),这样我们的存储号码簿中有同样姓氏的情况,就可以通过lower_bound返回的指针进行自增操作,直到姓氏不符为止。完整的代码如下,

点击(此处)折叠或打开

  1. #include "stdafx.h"
  2. #include <iostream>
  3. #include <string>
  4. #include <map>
  5. using namespace std;

  6. class Name {
  7. private:
  8.     string familyName;
  9.     string givenName;
  10. public:
  11.     Name(string FName = "", string GName = "") :
  12.             familyName(FName), givenName(GName) {
  13.     }
  14.     virtual ~Name() {
  15.     }
  16.     const string& getFamilyName() const {
  17.         return familyName;
  18.     }
  19.     const string& getGivenName() const {
  20.         return givenName;
  21.     }
  22.     bool operator <(const Name & rhs) const {
  23.         if (familyName < rhs.familyName) {
  24.             return true;
  25.         } else if (familyName == rhs.familyName) {
  26.             if (givenName < rhs.givenName)
  27.                 return true;
  28.         }
  29.         return false;
  30.     }
  31. };

  32. int _tmain(int argc, _TCHAR* argv[]) {
  33.     string NameArray[][3] =
  34.     { { "John", "Doe",     "3459483" },
  35.         { "Nick", "Bonham", "3492930" },
  36.         { "Jane", "Doe",     "2832819" },
  37.         { "Adam", "Clark", "6518324" },
  38.         { "Judy", "Foast", "9821572" },
  39.         { "Zeus", "Lenos", "4552341" },
  40.         { "Cole", "Minas", "1351244" },
  41.         { "Ooos", "Clark", "1562553" } };

  42.     map<Name, string> infoMap;
  43.     for (size_t i = 0; i < sizeof(NameArray) / (sizeof(string) * 3); i++) {
  44.         Name tmpName(NameArray[i][1], NameArray[i][0]);
  45.         infoMap.insert(pair<Name, string>(tmpName, NameArray[i][2]));
  46.     }

  47.     // display the sorted name and numbers
  48.     for (map<Name, string>::iterator iter = infoMap.begin();
  49.             iter != infoMap.end(); iter++) {
  50.         cout << iter->first.getGivenName() << " ";
  51.         cout << iter->first.getFamilyName() << " ";
  52.         cout << iter->second << endl;
  53.     }

  54.     while (true) {
  55.         cout << "Input the family name that you want to search: " << endl;
  56.         string aFmlyName;
  57.         cin >> aFmlyName;
  58.         if (aFmlyName == "exit")
  59.             break;
  60.         Name inputName(aFmlyName);
  61.         map<Name, string>::iterator iter = infoMap.lower_bound(inputName);
  62.         if (iter == infoMap.end() ||
  63.             iter->first.getFamilyName() != inputName.getFamilyName()) {
  64.             cout << "Nothing has been found, try again" << endl;
  65.             continue;
  66.         }

  67.         cout << "...here's the info that you need:" << endl;
  68.         while (true) {
  69.             cout << iter->first.getGivenName() << " ";
  70.             cout << iter->first.getFamilyName() << " ";
  71.             cout << iter->second << endl;
  72.             iter++;
  73.             if (iter == infoMap.end() ||
  74.                 iter->first.getFamilyName() != inputName.getFamilyName())
  75.                 break;
  76.         }
  77.     }
  78.     cout << " * * program terminated * *" << endl;
  79.     return 0;
  80. }
以下是输出,


阅读(1102) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~