C++Primer 第五版 练习10.12解答

本文详细解答了C++ Primer中的一个练习题,通过编写compareIsbn函数对比Sales_data对象,并利用该函数对vector中的Sales_data对象进行排序。文章记录了实现过程中的常见陷阱及其解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

练习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要求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<string>去重直接到vector<Sales_data>去重作者一定是想让你发现问题的,所以,作者不会无缘无故出一道你觉得好像重复的题目,做,就一定有收获,不做,当然也不会有损失。但这道题让我学到很多,最后,我诚挚的希望,如果你功底不错,既然一道题目列在那里了,你不妨把这道题给写完说清楚,这样对于像和我一样资质平平的大众应该是不错的资源,也能让大家受益很多。最后,上传的程序可能也存在错误,希望大家批评指教

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值