天天看點

C++primer(第五版)第七章程式設計題

練習7.1

/******************************************************************************
 * 使用2.6.1節聯系定義的Sales_data類為1.6節(第21頁)的交易處理程式編寫一個新版本。
 *****************************************************************************/
#include <iostream>

struct Sales_data
{
    std::string isbn;
    double price = 0.0;
    unsigned quantity = 0;
    double revenue = 0.0;
};

int main()
{
    Sales_data total; // 儲存下一條交易記錄的變量
    //讀入第一條交易記錄,并確定有資料可以處理
    if (std::cin >> total.isbn >> total.price >> total.quantity)
    {
        total.revenue = total.price * total.quantity;
        Sales_data trans; //儲存和的變量
        //讀入并處理剩餘交易記錄
        while (std::cin >> trans.isbn >> trans.price >> trans.quantity)
        {
            trans.revenue = trans.price * trans.quantity;
            //如果我們仍在處理相同的書
            if (total.isbn == trans.isbn)
                total.revenue += trans.revenue; //更新總銷售額
            else
            {
                //列印前一本書的結果
                std::cout << "ISBN:" << total.isbn << "\n單價:" << total.revenue / double(total.quantity) << "\n數量:" << total.quantity << "\n總銷售額:" << total.revenue << std::endl;
                //total現在表示下一本書的銷售額
                total.isbn = trans.isbn;
                total.price = trans.price;
                total.quantity = trans.quantity;
                total.revenue = trans.revenue;
            }
        }
        std::cout << "ISBN:" << total.isbn << "\n單價:" << total.revenue / double(total.quantity) << "\n數量:" << total.quantity << "\n總銷售額:" << total.revenue << std::endl;
    }
    else
    {
        //沒有輸入!警告讀者
        std::cerr << "No data?!" << std::endl;
        return -1; //表示失敗
    }
    return 0;
}
           

練習7.2

/******************************************************************************
 * 曾在2.6.2節的練習(第67頁)中編寫了一個Sales_data類,請向這個類添加combine和isbn
 * 成員。
 *****************************************************************************/
#include <iostream>
struct Sales_data
{
    std::string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    std::string bookNo;
    double price = 0.0;
    unsigned quantity = 0;
    double revenue = 0;
};

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    price += rhs.price;
    revenue += rhs.revenue;
    return *this;
}

int main()
{
    Sales_data book;
    std::cin >> book.bookNo >> book.quantity >> book.price; //讀入ISBN号、售出的冊數以及銷售價格
    double total_sales = book.quantity * book.price;
    double average_price = 0.0;
    if (book.quantity != 0)
    {
        average_price = total_sales / book.quantity;
        std::cout << book.bookNo << " " << book.quantity << " " << total_sales << " " << average_price << std::endl; //寫入ISBN号、銷售總額以及平均價格
    }
    else
        std::cout << "售出冊數為0" << std::endl;
    //以下為Sales_data的兩個對象的相加
    Sales_data book1;
    std::cin >> book1.bookNo >> book1.quantity >> book1.price; //寫入ISBN号、售出的冊數以及銷售價格
    if (book1.bookNo == book.bookNo)
    {
        book.quantity += book1.quantity;
        total_sales += book1.price * book1.quantity;
        if (book.quantity != 0)
        {
            average_price = total_sales / book.quantity;
            std::cout << book.bookNo << " " << book.quantity << " " << total_sales << " " << average_price << std::endl; //寫入ISBN号、銷售總額以及平均價格
        }
        else
            std::cout << "售出冊數為0" << std::endl;
    }
    else
        std::cout << "它們不是同一本書!" << std::endl;
    return 0;
}
           

練習7.3

/******************************************************************************
 * 修改7.1.1節(第229頁)的交易處理程式,令其使用這些成員。
 *****************************************************************************/
#include <iostream>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;

struct Sales_data
{
    //新成員:關于Sales_data對象的操作
    std::string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    double avg_price() const;

    //資料成員和2.6.1節(第64頁)相比沒有改變
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

int main()
{
    Sales_data total;                                             //儲存目前求和結果的變量
    if (cin >> total.bookNo >> total.units_sold >> total.revenue) //讀入第一筆交易
    {
        Sales_data trans;                                                //儲存下一條交易資料的變量
        while (cin >> trans.bookNo >> trans.units_sold >> trans.revenue) //讀取剩餘的交易
        {
            if (total.isbn() == trans.isbn()) //檢查isbn
                total.combine(trans);         //更新變量total目前的值
            else
            {
                cout << "ISBN:" << total.isbn() << "\n數量:" << total.units_sold << "\n均價:" << total.avg_price() << "\n總銷售額:" << total.revenue << endl; //輸出結果
                total = trans;                                                                                                                                   //處理下一本書
            }
        }
        cout << "ISBN:" << total.isbn() << "\n數量:" << total.units_sold << "\n均價:" << total.avg_price() << "\n總銷售額:" << total.revenue << endl; //輸出最後一條交易
    }
    else //沒有輸入任何資訊
    {
        cerr << "No data?!" << endl;
    }
}
           

練習7.4

/******************************************************************************
 * 編寫一個名為Person的類,使其表示人員的姓名和住址。使用string對象存放這些元素,接下
 * 來的練習将不斷充實這個類的其他特征。
 *****************************************************************************/
#include <iostream>

using std::cout;
using std::endl;
using std::string;

struct Person
{
    string name;
    string address;
};

int main()
{
    Person p;
    p.name = "qw";
    p.address = "er";
    cout << "姓名:" << p.name << "\n位址:" << p.address << endl;
    return 0;
}
           

練習7.5

/******************************************************************************
 * 在你的Person類中提供一些操作使其能夠傳回姓名和住址。這些函數是否應該是const的呢?
 * 解釋原因。
 *****************************************************************************/
#include <iostream>

using std::cout;
using std::endl;
using std::string;

struct Person
{
    string get_name() const { return name; } 
    string get_address() const { return address; }
    string name;
    string address;
};

int main()
{
    Person p;
    p.name = "qw";
    p.address = "er";
    cout << "姓名:" << p.get_name() << "\n位址:" << p.get_address() << endl;
    return 0;
}
           

練習7.6

/******************************************************************************
 * 對于函數add、read和print,定義你自己的版本。
 *****************************************************************************/
#include <iostream>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;

struct Sales_data
{
    //新成員:關于Sales_data對象的操作
    std::string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    double avg_price() const;

    //資料成員和2.6.1節(第64頁)相比沒有改變
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}

int main()
{
    Sales_data total;                                             //儲存目前求和結果的變量
    if (cin >> total.bookNo >> total.units_sold >> total.revenue) //讀入第一筆交易
    {
        Sales_data trans;                                                //儲存下一條交易資料的變量
        while (cin >> trans.bookNo >> trans.units_sold >> trans.revenue) //讀取剩餘的交易
        {
            if (total.isbn() == trans.isbn()) //檢查isbn
                total.combine(trans);         //更新變量total目前的值
            else
            {
                cout << "ISBN:" << total.isbn() << "\n數量:" << total.units_sold << "\n均價:" << total.avg_price() << "\n總銷售額:" << total.revenue << endl; //輸出結果
                total = trans;                                                                                                                                   //處理下一本書
            }
        }
        cout << "ISBN:" << total.isbn() << "\n數量:" << total.units_sold << "\n均價:" << total.avg_price() << "\n總銷售額:" << total.revenue << endl; //輸出最後一條交易
    }
    else //沒有輸入任何資訊
    {
        cerr << "No data?!" << endl;
    }
}
           

練習7.7

/******************************************************************************
 * 使用這些新函數重寫7.1.2節(第233頁)練習中的交易處理程式。
 *****************************************************************************/
#include <iostream>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;

struct Sales_data
{
    //新成員:關于Sales_data對象的操作
    std::string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    double avg_price() const;

    //資料成員和2.6.1節(第64頁)相比沒有改變
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}

int main()
{
    Sales_data total;     //儲存目前求和結果的變量
    if (read(cin, total)) //讀入第一筆交易
    {
        Sales_data trans;        //儲存下一條交易資料的變量
        while (read(cin, trans)) //讀取剩餘的交易
        {
            if (total.isbn() == trans.isbn()) //檢查isbn
                total = add(total, trans);    //更新變量total目前的值
            else
            {
                print(cout, total) << endl; //輸出結果
                total = trans;              //處理下一本書
            }
        }
        print(cout, total) << endl; //輸出最後一條交易
    }
    else //沒有輸入任何資訊
    {
        cerr << "No data?!" << endl;
    }
}
           

練習7.9

/******************************************************************************
 * 對于7.1.2節(第233頁)練習中的代碼,添加讀取和列印Person對象的操作。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

struct Person
{
    string get_name() const { return name; }
    string get_address() const { return address; }
    string name;
    string address;
};

istream &read(istream &is, Person &per)
{
    is >> per.name >> per.address;
    return is;
}

ostream &print(ostream &os, const Person &per)
{
    os << per.get_name() << " " << per.get_address();
    return os;
}

int main()
{
    Person per;
    read(cin, per);
    print(cout, per) << endl;
    return 0;
}
           

練習7.11

/******************************************************************************
 * 在你的Sales_data類中添加構造函數,然後編寫一段程式令其用到每個構造函數。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

struct Sales_data
{
    Sales_data() = default;
    Sales_data(const string &b) : bookNo(b) {}
    Sales_data(const string &b, unsigned u, double p) : bookNo(b), units_sold(u), revenue(p * u) {}
    Sales_data(istream &);
    //關于Sales_data對象的操作
    std::string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    double avg_price() const;
    //資料成員和2.6.1節(第64頁)相比沒有改變
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}

Sales_data::Sales_data(istream &is)
{
    read(is, *this);
}

int main()
{
    Sales_data sd0;
    print(cout, sd0) << endl;
    Sales_data sd1("QWER");
    print(cout, sd1) << endl;
    Sales_data sd2("TYUI", 1, 2);
    print(cout, sd2) << endl;
    Sales_data sd3(cin);
    print(cout, sd3) << endl;
}
           

練習7.12

/******************************************************************************
 * 把隻接受一個istream作為參數的構造函數定義移到類的内部。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

struct Sales_data
{
    Sales_data() = default;
    Sales_data(const string &b) : bookNo(b) {}
    Sales_data(const string &b, unsigned u, double p) : bookNo(b), units_sold(u), revenue(p * u) {}
    Sales_data(istream &is) { read(is, *this); }
    //關于Sales_data對象的操作
    string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    double avg_price() const;
    istream &read(istream &is, Sales_data &item);
    //資料成員和2.6.1節(第64頁)相比沒有改變
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &Sales_data::read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}
int main()
{
    Sales_data sd0;
    print(cout, sd0) << endl;
    Sales_data sd1("QWER");
    print(cout, sd1) << endl;
    Sales_data sd2("TYUI", 1, 2);
    print(cout, sd2) << endl;
    Sales_data sd3(cin);
    print(cout, sd3) << endl;
}
           

練習7.13

/******************************************************************************
 * 使用istream構造函數重寫第229頁的程式。
 *****************************************************************************/
#include <iostream>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

struct Sales_data
{
    Sales_data() = default;
    Sales_data(const string &b) : bookNo(b) {}
    Sales_data(const string &b, unsigned u, double p) : bookNo(b), units_sold(u), revenue(p * u) {}
    Sales_data(istream &is) { read(is, *this); }
    //關于Sales_data對象的操作
    string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    double avg_price() const;
    istream &read(istream &is, Sales_data &item);
    //資料成員和2.6.1節(第64頁)相比沒有改變
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &Sales_data::read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}
int main()
{
    Sales_data total(cin);
    if (total.isbn() != "")
    {
        
        while (true) //讀取剩餘的交易
        {
            Sales_data trans(cin);//儲存下一條交易資料的變量
            if(trans.isbn()=="") break;
            if (total.isbn() == trans.isbn()) //檢查isbn
                total = add(total, trans);    //更新變量total目前的值
            else
            {
                print(cout, total) << endl; //輸出結果
                total = trans;              //處理下一本書
            }
        }
        print(cout, total) << endl; //輸出最後一條交易
    }
    else //沒有輸入任何資訊
    {
        cerr << "No data?!" << endl;
    }
}
           

練習7.14

/******************************************************************************
 * 編寫一個構造函數,令其使用我們提供的類内初始值顯式地初始化成員。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

struct Sales_data
{
    Sales_data() {}
    //關于Sales_data對象的操作
    string isbn() const { return bookNo; }
    Sales_data &combine(const Sales_data &);
    double avg_price() const;
    istream &read(istream &is, Sales_data &item);
    //資料成員和2.6.1節(第64頁)相比沒有改變
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &Sales_data::read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}
int main()
{
    Sales_data sd0;
    print(cout, sd0) << endl;
}
           

練習7.15

/******************************************************************************
 * 為你的Person類添加正确的構造函數。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

struct Person
{
    Person() = default;
    Person(const string &n) : name(n) {}
    Person(const string &n, const string &a) : name(n), address(a) {}
    Person(istream &);
    string get_name() const { return name; }
    string get_address() const { return address; }
    string name;
    string address;
};

istream &read(istream &is, Person &per)
{
    is >> per.name >> per.address;
    return is;
}

ostream &print(ostream &os, const Person &per)
{
    os << per.get_name() << " " << per.get_address();
    return os;
}

Person::Person(istream &is)
{
    read(is, *this);
}
int main()
{
    Person per0;
    print(cout, per0) << endl;
    Person per1("qwer");
    print(cout, per1) << endl;
    Person per2("qwer", "tyui");
    print(cout, per2) << endl;
    Person per3(cin);
    print(cout, per3);
    return 0;
}
           

練習7.21

/******************************************************************************
 * 修改你的Sales_data類使其隐藏實作的細節。你之前編寫的關于Sales_data操作的程式應該
 * 繼續使用,借助類的新定義重新編譯該程式,確定其工作正常。
 *****************************************************************************/
#include <iostream>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

class Sales_data
{
    friend Sales_data add(Sales_data, const Sales_data);
    friend ostream &print(ostream &, const Sales_data &);

public:
    Sales_data() = default;
    Sales_data(const string &b) : bookNo(b) {}
    Sales_data(const string &b, unsigned u, double p) : bookNo(b), units_sold(u), revenue(p * u) {}
    Sales_data(istream &is) { read(is, *this); }
    //關于Sales_data對象的操作
    string isbn() const { return bookNo; }
    istream &read(istream &is, Sales_data &item);

private:
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    double avg_price() const;
    Sales_data &combine(const Sales_data &);
};

double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &Sales_data::read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}

int main()
{
    Sales_data total(cin);
    if (total.isbn() != "")
    {
        while (true) //讀取剩餘的交易
        {
            Sales_data trans(cin); //儲存下一條交易資料的變量
            if (trans.isbn() == "")
                break;
            if (total.isbn() == trans.isbn()) //檢查isbn
                total = add(total, trans);    //更新變量total目前的值
            else
            {
                print(cout, total) << endl; //輸出結果
                total = trans;              //處理下一本書
            }
        }
        print(cout, total) << endl; //輸出最後一條交易
    }
    else //沒有輸入任何資訊
    {
        cerr << "No data?!" << endl;
    }
}
           

練習7.22

/******************************************************************************
 * 修改你的Person類使其隐藏實作的細節。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

struct Person
{
    friend istream &read(istream &is, Person &per);

public:
    Person() = default;
    Person(const string &n) : name(n) {}
    Person(const string &n, const string &a) : name(n), address(a) {}
    Person(istream &);
    string get_name() const { return name; }
    string get_address() const { return address; }

private:
    string name;
    string address;
};

istream &read(istream &is, Person &per)
{
    is >> per.name >> per.address;
    return is;
}

ostream &print(ostream &os, const Person &per)
{
    os << per.get_name() << " " << per.get_address();
    return os;
}

Person::Person(istream &is)
{
    read(is, *this);
}
int main()
{
    Person per0;
    print(cout, per0) << endl;
    Person per1("qwer");
    print(cout, per1) << endl;
    Person per2("qwer", "tyui");
    print(cout, per2) << endl;
    Person per3(cin);
    print(cout, per3);
    return 0;
}
           

練習7.23

/******************************************************************************
 * 編寫你自己的Screen類。
 *****************************************************************************/
#include <iostream>

using std::cout;
using std::endl;
using std::string;

class Screen
{
public:
    using pos = string::size_type;
    Screen() = default;
    Screen(pos w) : width(w) {}
    Screen(pos w, pos h) : width(w), height(h) {}
    Screen(pos w, pos h, pos c) : width(w), height(h), cursor(c) {}
    Screen(pos w, pos h, pos c, char s) : width(w), height(h), cursor(c), contents(h * w, s) {}
    char get() const { return contents[cursor]; }
    char get(pos, pos) const;
    Screen &move(pos, pos);

private:
    pos cursor = 0, width = 0, height = 0;
    string contents;
};

char Screen::get(pos x, pos y) const
{
    pos row = x * width;
    return contents[row + y];
}

Screen &Screen::move(pos r, pos c)
{
    pos row = r * width;
    cursor = row + c;
    return *this;
}

int main()
{
    Screen s0(10, 10, 20, 'a');
    char a = s0.get();
    cout << a << "\n";
    s0.move(3, 4);
    a = s0.get(3, 4);
    cout << a << endl;
    return 0;
}
           

練習7.24

/******************************************************************************
 * 給你的Screen類添加三個構造函數:一個預設構造函數;另一個構造函數接受寬和高,然後将
 * content初始化成給定數量的空白;第三個構造函數接受寬和高的值以及一個字元,該字元作
 * 為初始化之後螢幕的内容。
 *****************************************************************************/
#include <iostream>

using std::cout;
using std::endl;
using std::string;

class Screen
{
public:
    using pos = string::size_type;
    Screen() = default;
    Screen(pos w, pos h) : width(w), height(h), contents(w * h, ' ') {}
    Screen(pos w, pos h, char s) : width(w), height(h), contents(h * w, s) {}
    char get() const { return contents[cursor]; }
    char get(pos, pos) const;
    Screen &move(pos, pos);

private:
    pos cursor = 0, width = 0, height = 0;
    string contents;
};

char Screen::get(pos x, pos y) const
{
    pos row = x * width;
    return contents[row + y];
}

Screen &Screen::move(pos r, pos c)
{
    pos row = r * width;
    cursor = row + c;
    return *this;
}

int main()
{
    Screen s0(10, 10), s1(10, 10, 's');
    for (unsigned i = 0; i != 10; ++i)
    {
        for (unsigned j = 0; j != 10; ++j)
            cout << s0.get(i, j);
        cout << endl;
    }
    for (unsigned i = 0; i != 10; ++i)
    {
        for (unsigned j = 0; j != 10; ++j)
            cout << s1.get(i, j);
        cout << endl;
    }
    return 0;
}
           

練習7.26

/******************************************************************************
 * 将Sales_data::avg_price定義成内聯函數。
 *****************************************************************************/
#include <iostream>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

class Sales_data
{
    friend Sales_data add(Sales_data, const Sales_data);
    friend ostream &print(ostream &, const Sales_data &);

public:
    Sales_data() = default;
    Sales_data(const string &b) : bookNo(b) {}
    Sales_data(const string &b, unsigned u, double p) : bookNo(b), units_sold(u), revenue(p * u) {}
    Sales_data(istream &is) { read(is, *this); }
    //關于Sales_data對象的操作
    string isbn() const { return bookNo; }
    istream &read(istream &is, Sales_data &item);

private:
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    double avg_price() const;
    Sales_data &combine(const Sales_data &);
};

inline double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &Sales_data::read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}

int main()
{
    Sales_data total(cin);
    print(cout, total) << endl;
    return 0;
}
           

練習7.27

/******************************************************************************
 * 給你自己的Screen類添加move、set和display函數,通過執行下面的代碼檢驗你的類是否正
 * 确。
 * Screen myScreen(5, 5, 'X');
 * myScreen.move(4,0).set('#').display(cout);
 * cout << "\n";
 * myScreen.display(cout);
 * cout << "\n";
 *****************************************************************************/
#include <iostream>

using std::cout;
using std::endl;
using std::string;

class Screen
{
public:
    using pos = string::size_type;
    Screen() = default;
    Screen(pos w) : width(w) {}
    Screen(pos w, pos h) : width(w), height(h), contents(w * h, ' ') {}
    Screen(pos w, pos h, char s) : width(w), height(h), contents(h * w, s) {}
    Screen &set(char);
    Screen &set(pos, pos, char);
    Screen &display(std::ostream &);
    const Screen &display(std::ostream &) const;
    char get() const { return contents[cursor]; }
    char get(pos, pos) const;
    Screen &move(pos, pos);

private:
    pos cursor = 0, width = 0, height = 0;
    string contents;
    void do_display(std::ostream &os) const { os << contents; }
};

inline Screen &Screen::display(std::ostream &os)
{
    do_display(os);
    return *this;
}
inline const Screen &Screen::display(std::ostream &os) const
{
    do_display(os);
    return *this;
}

inline Screen &Screen::set(char c)
{
    contents[cursor] = c;
    return *this;
}

inline Screen &Screen::set(pos r, pos col, char ch)
{
    contents[r * width + col] = ch;
    return *this;
}

char Screen::get(pos x, pos y) const
{
    pos row = x * width;
    return contents[row + y];
}

Screen &Screen::move(pos r, pos c)
{
    pos row = r * width;
    cursor = row + c;
    return *this;
}

int main()
{
    Screen myScreen(5, 5, 'X');
    myScreen.move(4,0).set('#').display(cout);
    cout << "\n";
    myScreen.display(cout);
    cout << "\n";
}
           

練習7.29

/******************************************************************************
 * 修改你的Screen類,令move,set和display函數傳回Screen并檢查程式的運作結果,再上一
 * 個練習中你的推測正确嗎?
 *****************************************************************************/
#include <iostream>

using std::cout;
using std::endl;
using std::string;

class Screen
{
public:
    using pos = string::size_type;
    Screen() = default;
    Screen(pos w) : width(w) {}
    Screen(pos w, pos h) : width(w), height(h), contents(w * h, ' ') {}
    Screen(pos w, pos h, char s) : width(w), height(h), contents(h * w, s) {}
    Screen set(char);
    Screen set(pos, pos, char);
    Screen display(std::ostream &);
    const Screen display(std::ostream &) const;
    char get() const { return contents[cursor]; }
    char get(pos, pos) const;
    Screen move(pos, pos);

private:
    pos cursor = 0, width = 0, height = 0;
    string contents;
    void do_display(std::ostream &os) const { os << contents; }
};

inline Screen Screen::display(std::ostream &os)
{
    do_display(os);
    return *this;
}
inline const Screen Screen::display(std::ostream &os) const
{
    do_display(os);
    return *this;
}

inline Screen Screen::set(char c)
{
    contents[cursor] = c;
    return *this;
}

inline Screen Screen::set(pos r, pos col, char ch)
{
    contents[r * width + col] = ch;
    return *this;
}

char Screen::get(pos x, pos y) const
{
    pos row = x * width;
    return contents[row + y];
}

Screen Screen::move(pos r, pos c)
{
    pos row = r * width;
    cursor = row + c;
    return *this;
}

int main()
{
    Screen myScreen(5, 5, 'X');
    myScreen.move(4, 0).set('#').display(cout);
    cout << "\n";
    myScreen.display(cout);
    cout << "\n";
}
           

練習7.31

/******************************************************************************
 * 定義一對類X和Y,其中X包含一個指向Y的指針,而Y包含一個類型為X的對象。
 *****************************************************************************/
#include <iostream>

using std::cout;

class Y;
class X
{
public:
    unsigned x = 0;
    Y *s;
};
class Y
{
public:
    unsigned y = 0;
    X s;
};
int main()
{
    X x1;
    Y y1;
    x1.s = &y1;
    x1.x = 1;
    y1.s = x1;
    y1.y = 2;
    cout << x1.x << " " << x1.s->y << " " << y1.y << " " << y1.s.x << "\n";
    return 0;
}
           

練習7.32

/******************************************************************************
 * 定義你自己的Screen和Window_mgr,其中clear是Window_mgr的成員,是Screen的友元
 *****************************************************************************/
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;
class Window_mgr;
class Screen
{
    friend Window_mgr;

public:
    using pos = string::size_type;
    Screen() = default;
    Screen(pos w) : width(w) {}
    Screen(pos w, pos h) : width(w), height(h), contents(w * h, ' ') {}
    Screen(pos w, pos h, char s) : width(w), height(h), contents(h * w, s) {}
    Screen &set(char);
    Screen &set(pos, pos, char);
    Screen &display(std::ostream &);
    const Screen &display(std::ostream &) const;
    char get() const { return contents[cursor]; }
    char get(pos, pos) const;
    Screen &move(pos, pos);

private:
    pos cursor = 0, width = 0, height = 0;
    string contents;
    void do_display(std::ostream &os) const { os << contents; }
};

class Window_mgr
{
public:
    using ScreenIndex = vector<Screen>::size_type;
    void clear(ScreenIndex);
    vector<Screen> screens{Screen(16, 10, '#')};
};

void Window_mgr::clear(ScreenIndex i)
{
    Screen &s = screens[i];
    s.contents = string(s.height * s.width, ' ');
}

inline Screen &Screen::display(std::ostream &os)
{
    do_display(os);
    return *this;
}
inline const Screen &Screen::display(std::ostream &os) const
{
    do_display(os);
    return *this;
}

inline Screen &Screen::set(char c)
{
    contents[cursor] = c;
    return *this;
}

inline Screen &Screen::set(pos r, pos col, char ch)
{
    contents[r * width + col] = ch;
    return *this;
}

char Screen::get(pos x, pos y) const
{
    pos row = x * width;
    return contents[row + y];
}

Screen &Screen::move(pos r, pos c)
{
    pos row = r * width;
    cursor = row + c;
    return *this;
}

int main()
{
    Window_mgr my_screens;
    my_screens.screens[0].display(cout);
    cout << endl;
    my_screens.clear(0);
    my_screens.screens[0].display(cout);
    return 0;
}
           

練習7.38

/******************************************************************************
 * 有些情況下我們希望提供cin作為接受istream參數的構造函數的預設實參,請聲明這樣的構造
 * 函數。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::istream;

class A
{
public:
    A(istream &is = cin) { is >> a; }
    unsigned a = 0;
};
int main()
{
    A q(cin);
    cout << q.a << "\n";
    A w;
    cout << w.a << "\n";
    return 0;
}
           

練習7.40

/******************************************************************************
 * 從下面的抽象概念中選擇一個(或者你自己指定一個),思考這樣的類需要哪些資料成員,提
 * 供一組合理的構造函數并闡明這樣做的原因。
 * (a)Book      (b)Date     (c)Employee
 * (d)Vehicle   (e)Object   (f)Tree
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::istream;

class Date
{
public:
    Date() = default;
    Date(unsigned y, unsigned m, unsigned d) : year(y), month(m), day(d) {}
    Date(unsigned y, unsigned m, unsigned d, unsigned h, unsigned mi, unsigned s) : year(y), month(m), day(d), hour(h), minute(mi), second(s) {}
    Date(istream &is) { is >> year >> month >> day >> hour >> minute >> second; }
    void display();

private:
    unsigned year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
};

void Date::display()
{
    cout << year << "-" << month << "-" << day << " " << hour << ":" << minute << ":" << second;
}

int main()
{
    Date d1, d2(1234, 5, 6), d3(7890, 12, 3, 4, 56, 7), d4(cin);
    d1.display();
    cout << "\n";
    d2.display();
    cout << "\n";
    d3.display();
    cout << "\n";
    d4.display();
    cout << "\n";
    return 0;
}
           

練習7.41

/******************************************************************************
 * 使用委托構造函數重新編寫你的Sales_data類,給每個構造函數體添加一條語句,令其一旦執
 * 行就列印一條資訊。用各種可能的方式分别建立Sales_data對象,認真研究每次輸出的資訊直
 * 到你确實了解了委托構造函數的執行順序。
 *****************************************************************************/
#include <iostream>

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
using std::string;

class Sales_data
{
    friend Sales_data add(Sales_data, const Sales_data);
    friend ostream &print(ostream &, const Sales_data &);

public:
    Sales_data() : Sales_data("", 0, 0) { cout << "委托構造函數已執行!\n"; }
    Sales_data(const string &b) : Sales_data(b, 0, 0) { cout << "委托構造函數已執行!\n"; }
    Sales_data(const string &b, unsigned u, double p) : bookNo(b),
                                                        units_sold(u),
                                                        revenue(p * u) {}
    Sales_data(istream &is) : Sales_data()
    {
        read(is, *this);
        cout << "委托構造函數已執行!\n";
    }
    //關于Sales_data對象的操作
    string isbn() const { return bookNo; }
    istream &read(istream &is, Sales_data &item);

private:
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    double avg_price() const;
    Sales_data &combine(const Sales_data &);
};

inline double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue / units_sold;
    else
        return 0;
}

Sales_data &Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; //把rhs的成員加到this對象的成員上
    revenue += rhs.revenue;
    return *this;
}

Sales_data add(Sales_data lhs, const Sales_data rhs)
{
    return lhs.combine(rhs);
}

istream &Sales_data::read(istream &is, Sales_data &item)
{
    double price = 0.0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " "
       << item.revenue << " " << item.avg_price();
    return os;
}

int main()
{
    Sales_data total,total1("asd"),total2("qwer",1,3),total3(cin);
    print(cout,total)<<endl;
    print(cout,total1)<<endl;
    print(cout,total2)<<endl;
    print(cout,total3)<<endl;
    return 0;
}
           

練習7.42

/******************************************************************************
 * 對于你在練習7.40(參見7.5.1節,第261頁)中編寫的類,确定哪些構造函數可以使用委托。
 * 如果可以的話,編寫委托構造函數。如果不可以,從抽象概念清單中重新選擇一個你認為可以
 * 使用委托構造函數的,為挑選出的這個概念編寫類定義。
 *****************************************************************************/
#include <iostream>

using std::cin;
using std::cout;
using std::istream;

class Date
{
public:
    Date() : Date(0, 0, 0, 0, 0, 0) {}
    Date(unsigned y, unsigned m, unsigned d) : Date(y, m, d, 0, 0, 0) {}
    Date(unsigned y, unsigned m, unsigned d, unsigned h, unsigned mi, unsigned s) : year(y), month(m), day(d), hour(h), minute(mi), second(s) {}
    Date(istream &is) : Date() { is >> year >> month >> day >> hour >> minute >> second; }
    void display();

private:
    unsigned year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
};

void Date::display()
{
    cout << year << "-" << month << "-" << day << " " << hour << ":" << minute << ":" << second;
}

int main()
{
    Date d1, d2(1234, 5, 6), d3(7890, 12, 3, 4, 56, 7), d4(cin);
    d1.display();
    cout << "\n";
    d2.display();
    cout << "\n";
    d3.display();
    cout << "\n";
    d4.display();
    cout << "\n";
    return 0;
}
           

練習7.43

/******************************************************************************
 * 假定有一個名為NoDefault的類,它有一個接受int的構造函數,但是沒有預設構造函數。定義
 * 類C,C有一個Nodefault類型的成員,定義C的預設構造函數。
 *****************************************************************************/
#include <iostream>
class NoDefault
{
public:
    NoDefault(int i) {}
};

class C
{
public:
    C() = default;

private:
    NoDefault n;
};

int main()
{
    C c; //無法引用 "C" 的預設構造函數 -- 它是已删除的函數
    return 0;
}
           

練習7.53

/******************************************************************************
 * 定義你自己的Debug。
 *****************************************************************************/
#include <iostream>

using std::cerr;

class Debug
{
public:
    constexpr Debug(bool b = true) : hw(b), io(b), ot(b) {}
    constexpr Debug(bool i, bool h, bool o) : io(i), hw(h), ot(o) {}
    constexpr bool any() { return io || hw || ot; }
    void set_io(bool b) { io = b; }
    void set_hw(bool b) { hw = b; }
    void set_ot(bool b) { ot = b; }

private:
    bool io;
    bool hw;
    bool ot;
};

int main()
{
    Debug io_sub(false, true, false);
    if (io_sub.any())
        cerr << "io,hw,ot中至少有一個沒有出錯!\n";
    Debug prod(false);
    if (prod.any())
        cerr<<"io,hw,ot全都不錯!\n";
    return 0;
}
           

練習7.57

/******************************************************************************
 * 編寫你自己的Account類。
 *****************************************************************************/
#include <iostream>

using std::cout;
using std::string;

class Account
{
public:
    void calculate() { amount += amount * interestRate; }
    static double rate() { return interestRate; }
    static void rate(double);

private:
    string owner;
    double amount;
    static double interestRate;
    static double initRate();
};

double Account::interestRate = 0.12;

void Account::rate(double newRate)
{
    interestRate = newRate;
}

int main()
{
    Account ac;
    ac.rate(0.34);
    ac.calculate();
    cout << ac.rate() << "\n";
    return 0;
}
           

繼續閱讀