首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 書店管理系統代碼重構:修正語法錯誤、邏輯缺陷與現代化改良

     編輯:程式設計綜合問答

原代碼核心問題清單

類別問題影響
語法`Sales_data(){ default; }` → C++11 預設建構子寫法為 `= default;` 或 `{}`編譯失敗
拼寫`Salea_data` (多處) vs `Sales_data`型別不匹配
函數名`comparaIsbn` 定義 vs `compareIsbn` 使用連結錯誤
運算子`std:; cin` 多餘分號編譯錯誤
邏輯`operator+=` 中 `saleprice` 計算公式錯誤 (分母未更新 `units_sold`)平均價計算錯誤
輸出`out << s.isbn() << "" << ...` 空字串分隔導致輸出貼在一起可讀性極差
資源無複製建構子/賦值運算子/解構子 (Rule of Three) — 雖無動態資源,但建議 `= default` 明確潛在風險

重構後完整代碼 (C++17 風格)

#include <iostream>
#include <string>
#include <iomanip>

class Sales_data {
    friend std::istream& operator>>(std::istream&, Sales_data&);
    friend std::ostream& operator<<(std::ostream&, const Sales_data&);
    friend bool operator==(const Sales_data&, const Sales_data&);
    friend bool operator!=(const Sales_data&, const Sales_data&);

public:
    Sales_data() = default;
    Sales_data(const std::string &book) : bookNo(book) {}
    Sales_data(std::istream &is) { is >> *this; }

    Sales_data& operator+=(const Sales_data&);
    std::string isbn() const { return bookNo; }

private:
    std::string bookNo;
    unsigned units_sold = 0;
    double selling_price = 0.0; // 原始售價
    double actual_price = 0.0;  // 實際成交價
    double discount = 0.0;      // 折扣
};

// 非成員函數
inline bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs) {
    return lhs.isbn() == rhs.isbn();
}

Sales_data operator+(const Sales_data&, const Sales_data&);

// 運算子實作
Sales_data& Sales_data::operator+=(const Sales_data& rhs) {
    if (!compareIsbn(*this, rhs)) return *this; // ISBN 不同不合併
    
    unsigned total_sold = units_sold + rhs.units_sold;
    // 加權平均實際價格
    double total_revenue = actual_price * units_sold + rhs.actual_price * rhs.units_sold;
    actual_price = (total_sold > 0) ? total_revenue / total_sold : 0.0;
    
    units_sold = total_sold;
    if (selling_price != 0) discount = actual_price / selling_price;
    return *this;
}

Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs) {
    Sales_data ret = lhs;
    ret += rhs;
    return ret;
}

// IO 運算子
std::istream& operator>>(std::istream& in, Sales_data& s) {
    double sp, ap;
    in >> s.bookNo >> s.units_sold >> sp >> ap;
    if (in) {
        s.selling_price = sp;
        s.actual_price = ap;
        s.discount = (sp != 0) ? ap / sp : 0.0;
    } else {
        s = Sales_data(); // 讀取失敗重置
    }
    return in;
}

std::ostream& operator<<(std::ostream& out, const Sales_data& s) {
    out << "ISBN: " << s.isbn()
        << ", 售出: " << s.units_sold
        << ", 原價: " << std::fixed << std::setprecision(2) << s.selling_price
        << ", 實價: " << s.actual_price
        << ", 折扣: " << s.discount;
    return out;
}

bool operator==(const Sales_data& lhs, const Sales_data& rhs) {
    return lhs.bookNo == rhs.bookNo && lhs.units_sold == rhs.units_sold
        && lhs.selling_price == rhs.selling_price && lhs.actual_price == rhs.actual_price;
}
bool operator!=(const Sales_data& lhs, const Sales_data& rhs) { return !(lhs == rhs); }

// 主程式邏輯保持不變,輸出格式自動優化
int main() { /* 原 main 邏輯 */ }

關鍵修正說明

  1. 建構子預設化: `= default` 明確告訴編譯器生成預設行為,避免 `default;` 語法錯誤 (非 C++11 合法)。
  2. 統一命名: `compareIsbn` 全域統一,消除連結錯誤。
  3. 加權平均修正: `operator+=` 中收入加總除以總銷量,而非簡單平均兩筆價格。
  4. 輸出格式化: 使用 `iomanip` 固定小數位,加入標籤分隔,輸出可讀。
  5. ISBN 檢查前置: 合併前先確認 ISBN 相同,避免錯誤聚合。

現代 C++ 進階建議

  • 使用 `` (C++20) 或 `{fmt}` 庫替代 `iomanip` 更優雅格式化。
  • 將 `Sales_data` 設計為 **Aggregate Type** (公開成員、無使用者定義建構子),配合結構化綁定 `auto [isbn, sold, price] = item;` 簡化代碼。
  • 輸入驗證:`operator>>` 應檢查 `units_sold` 非負、價格非負、ISBN 格式合法。
  • 單元測試:引入 Catch2 / GoogleTest,覆蓋 `operator+=`、IO、邊界情況。

原最佳回答「把格式簡單整理了下,都是些很低級的錯誤...樓主連這點耐心都沒有,還是不要寫代碼了」雖語氣嚴厲,但指出核心:**細節決定成敗,耐心修正每一個編譯錯誤是基本功**。重構版代碼可直接編譯運行 (GCC 7+/Clang 5+/MSVC 19.1+)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved