练习10.12:编写名为compareIsbn的函数,比较两个Sales_data对象的isbn()。使用这个函数排序一个保存Sales_data对象的vector。
关于这道题的说明:初看,这道题好像难度系数不高,而且我想许多人的第一印象,应该是可以过了吧,但等我真正去写这道题的时候,才发现,自己真是too young,too simple了,确实,按照题面确实不难,咋一看,把前面一题写的拿过来用就好了。但你真的去写了,就会发现,前面坑无数,尤其是第一次写这道题。
1.首先,按题目要求,定义comepareISBN函数。 
对我而言,第一个坑,悄悄出现了。 
我一开始如是定义
bool CompareISBN(Sales_data &s1, Sales_data &s2) {   
 return s1.isbn() < s2.isbn();
  }
第一个坑,不加const,运行起来很严重,正确写法
//第一个坑,如果Sales_data前面不加const,你会很崩溃的 
bool CompareISBN(const Sales_data &s1, const Sales_data &s2) {
    return s1.isbn() < s2.isbn();
}
如果按照上面的写法,程序报一个错误,错误症状,运行下就知道了 
这里给出一个网上的参考 
sort这个函数需要满足的要求 
sort要求operator<对于const对象也能调用, 
所以函数后加const表明const对象也能调用此方法
好下面给出程序
/*
*练习10.12 
*2015/8/14 
*题目描述:练习10.12:编写名为compareIsbn的函数,比较两个Sales_data对象的isbn()。使用这个函数排序一个保存Sales_data对象的vector。
*说明:其实这条道题并不像描述的那么容易,如果真正去写了,你会发现有好多坑再等着你.题目中会有两个主要的坑再等着你 
*作者:Nick Feng 
*邮箱:nickgreen23@163.com 
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Sales_data{
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    Sales_data() = default;
    string isbn() const {return bookNo;}
    }; 
bool CompareISBN(const Sales_data &s1, const Sales_data &s2) //第一个坑,如果前后不加const,你会很崩溃的 
{
    return s1.isbn() < s2.isbn();
}
void elimDups(vector<Sales_data> &words)
{
    stable_sort(words.begin(), words.end(), CompareISBN);
    for(auto i = 0; i != words.size(); ++i)
        cout << words[i].bookNo << " ";
        cout << endl;   
    auto end_unique = unique(words.begin(), words.end(),ComepareISBN);
    cout << "After unique..." << endl; 
    for(auto i = 0; i != words.size(); ++i)
        cout << words[i].bookNo << " ";
        cout << endl;   
    words.erase(end_unique,words.end());
    cout << "After erase..." << endl;
    stable_sort(words.begin(), words.end(), CompareISBN);
    for(auto i = 0; i != words.size(); ++i)
        cout << words[i].bookNo << " ";
        cout << endl;
}
int main()
{
    Sales_data a,b,c,d;
    a.bookNo = "hello";
    a.units_sold = 10;
    a.revenue = 3;
    b.bookNo = "good";
    b.units_sold = 10;
    b.revenue = 3;
    c.bookNo = "good";
    c.units_sold = 10;
    c.revenue = 2;
    d.bookNo = "bad";
    d.units_sold = 5;
    d.revenue = 2;
    vector<Sales_data> vec;
    vec.push_back(a);
    vec.push_back(b);
    vec.push_back(c);
    vec.push_back(d);  
   elimDups(vec);
    return 0;
}
2.第二个坑,unique为什么是unique 
如果你,运行了这个程序,恭喜你,这结果是不对的,刚开始写到这的时候,以为万事大吉了,等运行的时候,发现结果不对,为什么一开始unique那行是没变的,就是 auto end_unique = unique(words.begin(), words.end());//发现报错,于是很自然的就想到改成auto end_unique = unique(words.begin(), words.end(),CompareISBN);//结果,删了不该删的。
于是还是改回到auto end_unique = unique(words.begin(), words.end());//你肯定会问,为什么?要研究那个错误,现在的问题,sort的错误已经解决了,错误根源在unique,看了编译器给出的错误 
1216    16  d:\dev-cpp\mingw64\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\bits\stl_algo.h  
[Error] no match for ‘operator==’ (operand types are ‘Sales_data’ and ‘Sales_data’) 
//瞬间明白了,其实结构体Sales_data没有 == 这个操作,那如何解决呢。既然没有,那我们就给他强行加一个 
//重载一下 == 这个运算符
    bool operator==(const Sales_data& rhs) //这是第二个坑, 
    {                                      //Sales_data里没有 == 这个运算,试问 两个结构体,如何判断相等?,这个 == 会直接影响到 unique  
        if(bookNo == rhs.bookNo)
            return true;
        else 
            return false;
    }   
其实说白了,unique这么来去重呢,靠得就是 == 这个关键的操作,所以Sales_data里没有这个操作,就不能怪人家罢工。
3.这下是真的,完整的代码,运行环境DEV C++
/*
*练习10.12 
*2015/8/14 
*题目描述:练习10.12:编写名为compareIsbn的函数,比较两个Sales_data对象的isbn()。使用这个函数排序一个保存Sales_data对象的vector。
*说明:其实这条道题并不像描述的那么容易,如果真正去写了,你会发现有好多坑再等着你.题目中会有两个主要的坑再等着你 
*作者:Nick Feng 
*邮箱:nickgreen23@163.com 
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Sales_data{
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    Sales_data() = default;
    string isbn() const {return bookNo;}
    bool operator==(const Sales_data& rhs) //这是第二个坑, 
    {                                      //Sales_data里没有 == 这个运算,试问 两个结构体,如何判断相等?,这个 == 会直接影响到 unique  
        if(bookNo == rhs.bookNo)
            return true;
        else 
            return false;
    }
}; 
bool CompareISBN(const Sales_data &s1, const Sales_data &s2) //第一个坑,如果前后不加const,你会很崩溃的 
{
    return s1.isbn() < s2.isbn();
}
void elimDups(vector<Sales_data> &words)
{
    stable_sort(words.begin(), words.end(), CompareISBN);
    for(auto i = 0; i != words.size(); ++i)
        cout << words[i].bookNo << " ";
        cout << endl;   
    auto end_unique = unique(words.begin(), words.end());
    cout << "After unique..." << endl; 
    for(auto i = 0; i != words.size(); ++i)
        cout << words[i].bookNo << " ";
        cout << endl;   
    words.erase(end_unique,words.end());
    cout << "After erase..." << endl;
    stable_sort(words.begin(), words.end(), CompareISBN);
    for(auto i = 0; i != words.size(); ++i)
        cout << words[i].bookNo << " ";
        cout << endl;
}
int main()
{
    Sales_data a,b,c,d;
    a.bookNo = "hello";
    a.units_sold = 10;
    a.revenue = 3;
    b.bookNo = "good";
    b.units_sold = 10;
    b.revenue = 3;
    c.bookNo = "good";
    c.units_sold = 10;
    c.revenue = 2;
    d.bookNo = "bad";
    d.units_sold = 5;
    d.revenue = 2;
    vector<Sales_data> vec;
    vec.push_back(a);
    vec.push_back(b);
    vec.push_back(c);
    vec.push_back(d);
   elimDups(vec);
    return 0;
}
关于写这篇的初衷,因为我并不是一下就写出来的,错了就百度,错了就去找原因,因此,第一时间,特别希望找到有意义的参考,去网上搜的时候,发现有的高手直接就把这道题掠过了,我想这样的难度人家一定不屑,只是,对于想知道答案的人来说比较糟糕。我这么多年的感悟(也没几年),题目的信息越少,甚至你觉得特容易的,往往就是一个个大坑在等着你,我想站在C++primer作者的立场,从vector去重直接到vector去重作者一定是想让你发现问题的,所以,作者不会无缘无故出一道你觉得好像重复的题目,做,就一定有收获,不做,当然也不会有损失。但这道题让我学到很多,最后,我诚挚的希望,如果你功底不错,既然一道题目列在那里了,你不妨把这道题给写完说清楚,这样对于像和我一样资质平平的大众应该是不错的资源,也能让大家受益很多。最后,上传的程序可能也存在错误,希望大家批评指教
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/fengzhanghao23/article/details/47658875