現在我們已經解決了原始的書店問題了:我們必須讀取銷售記錄文件並生成一個報告,顯示出每本書的總共收入、平均售價和銷售數量。
練習24:
編寫一個程序來讀取幾個事務記錄。對於每個新讀取的事務記錄,檢測它的ISBN是否與前面的相同,計算每個ISBN有多少個事務記錄。通過給出幾條事務記錄來測試這個程序。這些事務應該有多個ISBN,但是每個ISBN的記錄應該集合在一起。
我們假設某個給定的ISBN的所有事務記錄是在一起出現的。我們的程序將把每個ISBN的數據組合到Sales_item對象total中。我們從標准輸入中讀取的每個事務都被保存在第二個Sales_item對象trans中。每次讀取新事務的時候,我們都會把它與total中的Sales_item對象比較。如果兩個對象的ISBN相同,我們就更新total。否則我們就打印total中的值,並把它設置為剛才讀取的事務記錄的值。
#include <iostream>
#include "Sales_item.h"
int main()
{
// 定義變量來保存進行中的和與下一個記錄
Sales_item total, trans;
// 需要處理數據嗎?
if (std::cin >> total) {
// 是的,讀取事務記錄
while (std::cin >> trans)
if (total.same_isbn(trans))
// 匹配,更新total
total = total + trans;
else {
// 不匹配,打印和賦值
std::cout << total << std::endl;
total = trans;
}
// 記得打印最後的記錄
std::cout << total << std::endl;
} else {
// 沒有輸入!提示用戶
std::cout << "No data?!" << std::endl;
return -1; // 表示失敗
}
return 0;
}
這個程序是我們到目前為止見到的最復雜的一個,但是它只使用了我們已經遇到的一些工具。像通常一樣,我們開始包含了標准類庫中的iostream和自己的類中的Sales_item.h頭文件。
在main中我們定義了所需要的對象:total用於統計給定ISBN的數據和,trans將保存我們讀取的事務記錄。我們先把一個事務讀入total中並測試讀取是否成功。如果讀取失敗了,那麼就沒有記錄了,我們跳到最外面的else分支,打印一條消息警告用戶沒有輸入信息。
假設成功地讀取了一條記錄,我們將執行if分支中的代碼。第一個語句是while,它將在所有剩余的記錄中進行循環。與前面的例子中的操作類似,我們的while條件從標准的輸入中讀取值並測試是否讀取了有效的數據。在例子中,我們把Sales_item對象讀入trans。只要讀取成功,我們就執行while的主體。
While的主體是一個if語句。我們測試兩個ISBN是否相同,如果相同,我們就把兩個對象相加並把結果存儲在total中。如果ISBN不同,我們就打印出total中存儲的值並把trans賦給total。在執行if之後,我們返回while條件,讀取下一個事務記錄,直到讀完記錄。
一旦while完成了,我們仍然必須寫出與最後的ISBN關聯的數據。當while結束的時候,total包含了文件中最後的ISBN,但是我們沒有機會打印它。我們在最後的語句代碼塊實現這個功能,它包含了最外面的if語句。
練習25:
使用Web站點中的Sales_item.h頭文件,編譯和執行這一部分中的書店程序。
練習26:
在書店程序中我們使用了加操作符而沒有使用符合賦值操作符把trans加上total。為什麼我們沒有使用符合賦值操作符?