標籤:c++peimer 練習10-12解答 comeisbn函數
練習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 *郵箱:[email protected] */#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 *郵箱:[email protected] */#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去重作者一定是想讓你發現問題的,所以,作者不會無緣無故出一道你覺得好像重複的題目,做,就一定有收穫,不做,當然也不會有損失。但這道題讓我學到很多,最後,我誠摯的希望,如果你功底不錯,既然一道題目列在那裡了,你不妨把這道題給寫完說清楚,這樣對於像和我一樣資質平平的福士應該是不錯的資源,也能讓大家受益很多。最後,上傳的程式可能也存在錯誤,希望大家批評指教
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
C++Primer 第五版 練習10.12解答