C++ Primer Plus章节编程练习第十章

1

题目

  为复习题5描述的类提供方法定义,并编写一个小程序来演示所有的特性。

题解

#include<iostream>
#include<string>
class Account{
private:
    std::string name_;
    int id_;
    double savings_;
public:
    Account();
    Account(const std::string &name,int id,double savings=0.0);
    ~Account();
    //存款
    void deposit(double numbers);
    //取款
    void withdrawal(double numbers);
    void show()const;
};
//默认构造函数
Account::Account(){
    name_="no name";
    id_=0;
    savings_=0.0;
}
//重载的构造函数
Account::Account(const std::string &name,int id,double savings){
    name_=name;
    if(savings<0){
        std::cout<<"Number of savings can't be negative; "
                 <<name<<"'s savings set to 0\n";
        savings_=0;
    }
    else
        savings_=savings;
    id_=id;
}
//析构函数
Account::~Account(){
}
void Account::deposit(double number){
    if(number<0){                                           //存款不可为负数
        std::cout<<"Number of deposit money can't be negetive."
                 <<"Transaction is borted.\n";
    }
    else{
        savings_+=number;
    }
}
void Account::withdrawal(double number){
    using std::cout;
    if(number<0){                                           //取款不可为负数
        cout<<"Number of withdrawal money can't be negative "
            <<"Transaction is aborted\n";
    }
    else if(number>savings_){                               //取款不可大于账户金额
        cout<<"You can't withdrawal more than you have! "
            <<"Transaction is aborted.\n";
    }
    else
        savings_-=number;
}
void Account::show()const{
    using std::cout;
    using std::endl;
    cout<<"Here is the info of your account:\n";
    cout<<"Name: "<<name_<<endl
        <<"ID: #"<<id_<<endl
        <<"Savings: $"<<savings_<<endl;
}
int main(){
    using namespace std;
    Account one;
    one.show();
    Account two("People name",1,3000.0);
    two.show();
    two.deposit(1000.0);
    two.show();
    two.withdrawal(500000.0);
    two.withdrawal(333.0);
    two.show();
    return 0;
}

2

题目

  下面是一个非常简单的类的定义:

class Person{
private:
    static const int LIMIT=25;
    string lname;
    char fname[LIMIT];
public:
    Person(){lname="";fname[0]='\0';}
    Person(const string &ln,const char *fn="Heyyou");
    void Show()const;           //Firstname lastname 格式
    void FormalShow()const;     //Lastname Firstname 格式
};

  它使用了一个string 对象和一个字符数组,让您能够比较它们的用法。请提供未定义的方法的代码,以完成这个类的实现。再编写一个使用这个类的程序,它使用了三种可能的构造函数调用(没有参数、一个参数和两个参数)以及两种显示方法。下面是一个使用这些构造函数和方法的例子:

Person one;
Person two("Smythecraft");
Person three("Dimwiddy", "Sam");
one.Show();
cout<<endl;
one.FormalShow();
//etc. for tow and three

题解

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
class Person{
private:
    static const int LIMIT=25;
    string lname;
    char fname[LIMIT];
public:
    Person(){lname="";fname[0]='\0';}
    Person(const string &ln,const char *fn="Heyyou");
    void Show()const;           //Firstname lastname 格式
    void FormalShow()const;     //Lastname Firstname 格式
};
Person::Person(const string &ln,const char*fn){
    lname=ln;
    strcpy(fname,fn);
}
void Person::Show()const{
    cout<<fname<<", "<<lname<<endl;
}
void Person::FormalShow()const{
    cout<<lname<<", "<<fname<<endl;
}
int main(){
    Person one;
    Person two("Smythecraft");
    Person three("Dimwiddy","Sam");
    one.Show();
    one.FormalShow();
    two.Show();
    two.FormalShow();
    three.Show();
    three.FormalShow();
    return 0;
}

3

题目

  完成第9章的编程练习1,但要用正确的golf类声明替换那里的代码。用带合适参数的构造函数替换setgolf(golf &, const char*, int),以提供初始值。保留setgolf()的交互版本,但要用构造函数来实现它(例如,setgolf()的代码应该获得数据,将数据传递给构造函数来创建一个临时对象,并将其赋给调用对象,即*this)。

题解

#include<iostream>
#include<cstring>
using namespace std;
class golf{
private:
    static const int LEN=40;
    char fullname_[LEN];
    int handicap_;
public:
    golf();
    golf(const char* name, int hc);
    int setgolf();
    void handicap(int hc);
    void showgolf()const;
};
golf::golf(){

}
golf::golf(const char* name, int hc){
    strcpy(fullname_,name);
    handicap_=hc;
}
int golf::setgolf(){
    cout<<"Enter the name: ";
    cin.getline(fullname_,LEN);
    if(fullname_[0]=='\0') return 0;             //如果读入空行,则返回0
    cout<<"Enter the handicap: ";
    cin>>handicap_;
    return 1;
}
void golf::handicap(int hc){
    handicap_=hc;
}
void golf::showgolf()const{
    cout<<"Name: "<<fullname_<<endl;
    cout<<"Handicap: "<<handicap_<<endl;
}
int main(){
    golf first("First one",1),second;           //自定义的构造函数,默认构造函数
    first.showgolf();
    if(second.setgolf()){                       //带交互的函数
        cout<<"Set second successfully!"<<endl;
        second.showgolf(); 
    }
    else
        cout<<"Set second unsuccessfully!"<<endl;
    first.handicap(3);
    first.showgolf();  
    return 0;
}

4

题目

  完成第9章的编程练习4,但将Sales结构及相关的函数转换为一个类及其方法。用构造函数替换setSales(sales &,double [],int) 函数。用构造函数实现setSales(Sales &)方法的交互版本。将类保留在名称空间SALES中。

题解

#include<iostream>
namespace SALES{
    class Sales{
    private:
        static const int QUARTERS=4;
        double sales[QUARTERS];
        double average;
        double max;
        double min;
    public:
        //提示并读入四个数字,计算并存入对应的成员变量中
        Sales();
        //从ar中复制最多4个或者n个到s的sales成员中,计算平均值和最大最小值并存到对应的成员变量中
        Sales(const double ar[],int n);
        ~Sales(){};
        //显示结构体
        void showSales()const;
    };
    Sales::Sales(){
        using std::cout;
        using std::cin;
        cout<<"Enter 4 numbers as the seales:"<<std::endl;
        double sum=0.0;
        for(int i=0;i<QUARTERS;i++){
            cin>>sales[i];
            sum+=sales[i];
            if(i==0) max=min=sales[i];
            else{
                if(sales[i]>max) max=sales[i];
                if(sales[i]<min) min=sales[i];
            }
        }
        average=sum/QUARTERS;
    }
    Sales::Sales(const double ar[],int n){
        if(n<=0) return;
        n=n<QUARTERS?n:QUARTERS;
        double sum=0.0;
        max=min=ar[0];
        int i;
        for(i=0;i<n;i++){
            sum+=ar[i];
            sales[i]=ar[i];
            if(ar[i]>max) max=ar[i];
            if(ar[i]<min) min=ar[i];
        }
        //如果小于4个则,将其他置零
        if(i<QUARTERS) for(;i<QUARTERS;i++) sales[i]=0.0;
        average=sum/QUARTERS;
    }
    void Sales::showSales()const{
        using std::cout;
        using std::endl;
        cout<<"Sales for 4 quarters as following:\n";
        for(int i=0;i<QUARTERS;i++){
            if(i) putchar(' ');
            cout<<sales[i];
        }
        cout<<endl;
        cout<<"The average of all sales: "<<average<<endl;
        cout<<"The max sale: "<<max<<endl;
        cout<<"The min sale: "<<min<<endl;
    }
}
int main(){
    SALES::Sales one;
    double mysales[]={100.2, 200.3, 300.4, 400.5};
    SALES::Sales two(mysales,3);
    one.showSales();
    two.showSales();
    return 0;
}

5

题目

  考虑下面的结构声明:

struct customer{
    char fullname[35];
    double payment;
};

  编写一个程序,它从栈中添加和删除customer 结构(栈用Stack类声明表示)。每次customer结构被删除时,其payment的值都被加入到总数中,并报告总数。注意:应该可以直接使用Stack类而不作修改:只需修改typedef声明,使Item的类型为customer,而不是unsigned long即可。

题解

#include<iostream>
#include<cctype>
struct customer{
    char fullname[35];
    double payment;
};
typedef customer Item;
class Stack{
private:
    enum{MAX=10};
    Item items[MAX];
    int top;
public:
    Stack();
    bool isempty()const;
    bool isfull()const;
    bool push(const Item &item);
    bool pop(Item &item);
};
Stack::Stack(){
    top=0;
}
bool Stack::isempty()const{
    return top==0;
}
bool Stack::isfull()const{
    return top==MAX;
}
bool Stack::push(const Item &item){
    if(top<MAX){
        items[top++]=item;
        return true;
    }
    else
        return false;
}
bool Stack::pop(Item &item){
    if(top>0){
        item=items[--top];
        return true;
    }
    else
        return false;
}
int main(){
    using namespace std;
    Stack st;
    char ch;
    double total_payment=0.0;
    customer temp;
    cout<<"Please enter A to add a Purchase order,\n"
        <<"p to process a PO, or Q to quit.\n";
    while(cin>>ch&&toupper(ch)!='Q'){
        while(cin.get()!='\n')
            continue;
        if(!isalpha(ch)){
            cout<<"\a";
            continue;
        }
        switch(ch){
            case 'A':
            case 'a': cout<<"Enter a PO customer to add: "<<endl
                          <<"Enter his or her fullname first: ";
                      cin.getline(temp.fullname,35);            //提示并输入一个顾客信息
                      cout<<"Enter his or her payment: ";
                      cin>>temp.payment;
                      cin.get();                //吸收换行
                      if(st.isfull())
                        cout<<"stack already full\n";
                      else
                        st.push(temp);
                      break;
            case 'P':
            case 'p': if(st.isempty())
                        cout<<"Stack already empty\n";
                      else{
                          st.pop(temp);
                          total_payment+=temp.payment;          //出栈时统计支付金额
                          cout<<"PO #"<<temp.fullname<<" popped\n";
                          cout<<"This customer's payment: $"<<temp.payment<<endl;
                          cout<<"Now, total payment = $"<<total_payment<<endl;
                      } 
                      break;
        }
        cout<<"Please enter A to add a purchase order,\n"
            <<"P to process a PO, or Q to quit.\n";
    }
    cout<<"Bye\n";
    return 0;
}

6

题目

  下面是一个类声明:

class Move{
private:
    double x;
    double y;
public:
    Move(double a=0,double b=0);
    void showmove()const;
    Move add(const Move &m)const;
    void reset(double a=0,double b=0);
};

  请提供成员函数的定义和测试这个类的程序。

题解

#include<iostream>
class Move{
private:
    double x;
    double y;
public:
    Move(double a=0,double b=0);
    void showmove()const;
    Move add(const Move &m)const;
    void reset(double a=0,double b=0);
};
Move::Move(double a,double b){
    x=a;
    y=b;
}
void Move::showmove()const{
    std::cout<<x<<", "<<y<<std::endl;
}
Move Move::add(const Move&m)const{
    return Move(x+m.x,y+m.y);
}
void Move::reset(double a,double b){
    x=a,y=b;
}
int main(){
    using namespace std;
    Move one;
    Move two(1);
    Move three(2,3);
    Move four=three.add(two);
    cout<<"One: ";
    one.showmove();
    cout<<"Two: ";
    two.showmove();
    cout<<"Three: ";
    three.showmove();
    cout<<"Four: ";
    four.showmove();
    four.reset(5,5);
    cout<<"After reset to (5,5), four: ";
    four.showmove();
    return 0;
}

7

题目

  Betelgeusean plorg有这些特性。
  数据:
  ● plorg的名称不超过19个字符;
  ● plorg有满意指数(CI),这是一个整数。
  操作:
  ● 新的plorg将有名称,其CI值为50;
  ● plorg的CI可以修改;
  ● plorg可以报告其名称和CI;
  ● plorg的默认名称为“Plorga"。
  请编写一个Plorg类声明(包括数据成员和成员函数原型)来表示plorg,并编写成员函数的函数定义。然后编写一个小程序,以演示Plorg类的所有特性。

题解

#include<iostream>
#include<cstring>
using namespace std;
class Plorg{
private:
    static const int LEN=20;
    char name_[LEN];
    int CI_;
public:
    Plorg(const char *name="Plorga",int CI=50);
    ~Plorg(){};
    void rename(const char* name);
    void setCI(int CI);
    const char* name();
    int CI();
    void showplorg();
};
Plorg::Plorg(const char* name,int CI){
    strcpy(name_,name);
    CI_=CI;
}
void Plorg::rename(const char * name){
    strcpy(name_,name);
}
void Plorg::setCI(int CI){
    CI_=CI;
}
const char* Plorg::name(){
    return name_;
}
int Plorg::CI(){
    return CI_;
}
void Plorg::showplorg(){
    cout<<"Name: "<<name_<<endl;
    cout<<"CI: "<<CI_<<endl;
}
int main(){
    Plorg one;
    Plorg two("Name of two",30);
    one.showplorg();
    two.showplorg();
    one.rename("Name of one");
    one.showplorg();
    two.setCI(100);
    cout<<"After setCI of two:\n";
    cout<<"Get name of two: "<<two.name()<<endl;
    cout<<"Get CI of two: "<<two.CI()<<endl;
    return 0;
}

8

题目

  可以将简单列表描述成下面这样:
  ● 可存储0或多个某种类型的列表;
  ● 可创建空列表;
  ● 可在列表中添加数据项;
  ● 可确定列表是否为空;
  ● 可确定列表是否为满;
  ● 可访问列表中的每一个数据项, 并对它执行某种操作。
  可以看到,这个列表确实很简单,例如,它不允许插入或删除数据项。
  请设诈一个List类来表示这种抽象类型。您应提供头文件list.h和实现文件list.cpp,前者包含类定义,后者包含类方法的实现。您还应创建一个简短的程序来使用这个类。该列表的规范很简单,这主要旨在简化这个编程练习。可以选择使用数组或链表来实现该列表,但公有接口不应依赖于所做的选择。也就是说,公有接口不应有数组索引、节点指针等。应使用通用概念来表数的函数来处理:

void visit (void (*pf)(Item &));

  其中,pf指向一个将ltem引用作为参数的函数(不是成员函数),Item是列表中数据项的类型。visit()函数将该函数用于列表中的每个数据项。

题解

  头文件list.h:

#ifndef LIST_H_
#define LIST_H_
typedef int ITEM;
class List{
private:
    static const int MAX=50;
    ITEM items_[MAX];
    int index_;
    int max_;
public:
    List();
    //创建一个存储能力为n的List
    List(int n);
    bool add(const ITEM &e);
    bool isempty();
    bool isfull();
    bool visit(void (*pf)(ITEM &e));
    ~List();
};
#endif

  源文件list.cpp:

#include<iostream>
#include"list.h"
List::List(){
    max_=MAX;
    index_=0;
}
List::List(int n){
    if(n>MAX){
        max_=MAX;
        std::cout<<"You can't have a List with more than max capacity!\n"
                 <<"Set the list's capacity to MAX: 50\n";
    }
    else
        max_=n;
    index_=0;
}
bool List::add(const ITEM &e){
    if(isfull()) return false;
    items_[index_++]=e;
    return true;
}
bool List::isempty(){
    return index_==0;
}
bool List::isfull(){
    return index_==max_;
}
bool List::visit(void (*pf)(ITEM &e)){
    if(isempty()) return false;
    for(int i=0;i<index_;i++)
        pf(items_[i]);
    return true;
}
List::~List(){
}

  源文件8.cpp:

//与list.cpp一起编译
#include<iostream>
#include"list.h"
void AddTen(ITEM &e){
    e+=10;
}
void PrintItem(ITEM &e){
    printf("%d ",e);
}
int main(){
    using namespace std;
    //默认构造函数
    List listone;
    //指定大小的构造函数
    List listtwo(10);
    //指定超过容量的构造函数
    List listthree(100);
    //给listtwo添加10个元素0~9
    for(int i=0;i<10;i++)
        listtwo.add(i);
    if(listone.isempty()) printf("List one is empty!\n");
    if(listtwo.isfull()) printf("List two is full!\n");
    //输出listtwo
    listtwo.visit(PrintItem);
    cout<<endl;
    //给listtwo的每个元素加十
    listtwo.visit(AddTen);
    //在输出listtwo
    listtwo.visit(PrintItem);
    cout<<endl;
    return 0;
}

当珍惜每一片时光~