Practice6_2_map_sort_by_comparator

上一个程序初步简单的实现了使用自定义operator的方式的map的初始化,但是遇到了一个问题:

检查operator函数时报“invalid operator<”错误,程序崩了。下午找出原 
因。下一个程序中解决该问题,并实现高内聚。

“invalid operator<”错误的原因是(具体见这里):

在待排序列中如果出现相等元素,则会报错Expression : invalid operator < 

原因是,c++编译器检测到调用cmp的参数a==b时,c++编译器会立即用反序参数调用cmp函数,即调用cmp(b,a),来判断cmp函数是否已经执行了严格的弱序规则(a与b相等则位置不被改变)

于是,重新实现operator中的条件判断及返回值,这两点就是解决问题的关键。调试通过,程序能正常运行。

// Practice6_map_sort_by_comparator.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <map>
#include <string>
#include <iostream>

using namespace std;

typedef struct tagStudentInfo
{
       int      stuId;
       string   stuName;
}StudentInfo; 

/* 两种方式实现操作符函数,一种是struct,另一种是class加public
struct CompareStu
{
    int operator()(const StudentInfo &x, const StudentInfo &k) const
    {
        if(k.stuId > x.stuId) return 1;//这里必须是大于,并且return true,原因见参考链接
        else return x.stuName.compare(k.stuName) > 0;
  }
};*/

/* 另一种是class加public
class CompareStu
{
public:
    int operator()(const StudentInfo &x, const StudentInfo &k) const
    {
        if(k.stuId > x.stuId) return 1;//这里必须是大于,并且return true,原因见参考链接
        else return x.stuName.compare(k.stuName) > 0;
  }
};*/

/* 上面的两种实现在使用for循环insert数据时是有问题的,主要在于两元素相等时的返回值,下面这种可编译通过*/
class CompareStu
{
public:
    int operator()(const StudentInfo &x, const StudentInfo &k) const
    {
        if(k.stuId != x.stuId) 
            return k.stuId > x.stuId;//这里必须是大于,并且return true,原因见参考链接
        else 
            return k.stuName.compare(x.stuName) > 0;
  }
};

/* 第一种初始化方式*/
void initMap( map<StudentInfo, int, CompareStu> &mapStu)
{
     StudentInfo studentInfo;
     studentInfo.stuId = 1;
     studentInfo.stuName = "student_one";
     mapStu.insert(pair<StudentInfo, int>(studentInfo, 90));
     studentInfo.stuId = 2;
     studentInfo.stuName = "student_two";
     mapStu.insert(pair<StudentInfo, int>(studentInfo, 80));
}

string strs[5] = {"huawei", "xiaomi", "meizu", "oppo", "vivo"};
/* 第二种初始化方式*/
void initMapByPair(map<StudentInfo, int, CompareStu> &mapStu, unsigned int size)
{
    StudentInfo si = {0, ""}; //两种方式实现StudentInfo的初始化,一种是先声明后赋值,另一种直接在循环中初始化。不能混用!!为啥??
    for(unsigned int i = 0; i < size; i++)
    {
        si.stuId = i + 1;
        si.stuName = strs[i];
        mapStu.insert(pair<StudentInfo, int>(si, i + 90));
    }
}

void printMap(map<StudentInfo, int, CompareStu> mapStu)
{
        map<StudentInfo, int, CompareStu>::iterator iter= mapStu.begin();
        for(; iter != mapStu.end(); iter++)
        {
            cout << iter->first.stuId << "," << iter->first.stuName << "," << iter->second << endl;
        }
}

int main()
{
       map<StudentInfo, int, CompareStu> mapStudent;
      //initMap(mapStudent);
       initMapByPair(mapStudent, 5);//第二种初始化方式

        printMap(mapStudent);
}

运行结果:

1,huawei,90
2,xiaomi,91
3,meizu,92
4,oppo,93
5,vivo,94

posted on 2017-03-04 19:59  cleverlzc  阅读(146)  评论(0编辑  收藏  举报