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

1

题目

  对于下面的类声明:

class Cow{
private:
    char name[20];
    char* hobby;
    double weight;
public:
    Cow();
    Cow(const char* nm,const char* ho,double wt);
    Cow(const Cow &c);
    ~Cow();
    Cow& operator=(const Cow &c);
    void ShowCow()const;
};

  给这个类提供实现,并编写一个使用所有成员函数的小程序。

题解

#include<iostream>
#include<cstring>
using namespace std;
class Cow{
private:
    char name[20];
    char* hobby;
    double weight;
public:
    Cow();
    Cow(const char* nm,const char* ho,double wt);
    Cow(const Cow &c);
    ~Cow();
    Cow& operator=(const Cow &c);
    void ShowCow()const;
};
Cow::Cow(){
    name[0]='\0';
    hobby=nullptr;
    weight=0;
}
Cow::Cow(const char* nm,const char* ho,double wt){
    int lena=strlen(nm);                //name的复制不能超过最长长度
    int len=lena>19?19:lena;
    memcpy(name,nm,len); name[len]='\0';//使用memcpy,最后置为0
    lena=strlen(ho);                    //hobby使用深层复制
    hobby=new char[lena+1];
    strcpy(hobby,ho);
    weight=wt;
}
Cow::Cow(const Cow &c){
    strcpy(name,c.name);
    int len=strlen(c.hobby);
    hobby=new char[len+1];
    strcpy(hobby,c.hobby);
    weight=c.weight;
}
Cow::~Cow(){
    delete [] hobby;
}
Cow& Cow::operator=(const Cow &c){
    if(this==&c)
        return *this;
    strcpy(name,c.name);
    int len=strlen(c.hobby);
    delete[] hobby;
    hobby=new char[len+1];
    strcpy(hobby,c.hobby);
    weight=c.weight;
    return *this;
}
void Cow::ShowCow()const{
    cout<<"Name  : "<<name<<endl;
    cout<<"Hobby : "<<(hobby?hobby:"null")<<endl;   //初始化为空的时候无法输出,所以要进行判定
    cout<<"Weight: "<<weight<<endl;
}
//**************************main函数**************************
int main(){
    Cow one;
    Cow two("tow","eating",50);
    Cow three;
    three=two;
    Cow four(two);
    one.ShowCow();
    two.ShowCow();
    three.ShowCow();
    four.ShowCow();
    return 0;
}

2

题目

  通过完成下面的工作来改进String类声明(即将String1.h升级为String2.h)。
  a.对+运算符进行重载,使之可将两个字符串合并成1个。
  b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)。
  c.提供String()成员函数,将字符串中所有字母字符转换成大写。
  d.提供一个这样的成员函数,它接受-一个char参数,返回该字符在字符串中出现的次数。
  使用下面的程序来测试您的工作:

int main(){
    String s1(" and I am a C++ student.");
    String s2="Please enter your name: ";
    String s3;
    cout<<s2;
    cin>>s3;
    s2="My name is "+s3;
    cout<<s2<<".\n";
    s2=s2+s1;
    s2.Stringup();
    cout<<"The string\n"<<s2<<"\ncontains "<<s2.has('A')
        <<" 'A' characters in it.\n";
    s1="red";
    String rgb[3]={String(s1),String("green"),String("blue")};
    cout<<"Enter the name of a primary color for mixing light: ";
    String ans;
    bool success=false;
    while(cin>>ans){
        ans.Stringlow();
        for(int i=0;i<3;i++){
            if(ans==rgb[i]){
                cout<<"That's right!\n";
                success=true;
                break;
            }
        }
        if(success)
            break;
        else
            cout<<"Try again!\n";
    }
    cout<<"Bye\n";
    return 0;
}

  输出应与下面相似:

Please enter your name: Fretta Farbo
My name is Fretta Farbo.
The string
My NAME IS FRETTA FARBO AND I AM A C== STUDENT.
contains 6 'A' characters in it.
Enter the name of a primary color for mixing light: yellow
Try again!
BLUE
That's right!
Bye

题解

#include<iostream>
#include<cstring>
using namespace std;
class String{
private:
    char *str;
    int len;
    static int num_strings;
    static const int CINLIM=80;
public:
    String(const char*s);
    String();
    //复制构造函数
    String(const String&);
    ~String();
    int length()const{return len;}
    //重载赋值运算符
    String& operator=(const String&);   //用一个类对象给另一个赋值
    String& operator=(const char*);     //用字符串给对象赋值
    char& operator[](int i);            //取下标,可修改
    const char&operator[](int i)const;  //const取下标,不可修改
    //重载比较运算符
    friend bool operator<(const String &st1,const String &st2);
    friend bool operator>(const String &st1,const String &st2);
    friend bool operator==(const String &st1,const String &st2);
    //重载输入输出运算符
    friend ostream& operator<<(ostream& os,const String&st);
    friend istream& operator>>(istream& is,String &st);
    //静态成员函数
    static int HowMany();

    //课后题扩充
    //重载+运算符
    String& operator+(const String &st);
    friend String& operator+(const char* str,String &st);
    void Stringlow();                   //转化小写
    void Stringup();                    //转化大写
    int has(char ch)const;              //统计字符个数

};
int String::num_strings=0;
int String::HowMany(){
    return num_strings;
}
String::String(const char*s){
    len=strlen(s);
    str=new char[len+1];
    strcpy(str,s);
    num_strings++;
}
String::String(){
    len=0;
    str=new char[1];
    str[0]='\0';
    num_strings++;
}
String::String(const String &st){
    num_strings++;
    len=st.len;
    str=new char[len+1];
    strcpy(str,st.str);
}
String::~String(){
    --num_strings;
    delete[] str;
}
String & String::operator=(const String &st){
    if(this==&st)
        return *this;
    delete[] str;
    len=st.len;
    str=new char[len+1];
    strcpy(str,st.str);
    return *this;
}
String & String::operator=(const char*s){
    delete[] str;
    len=strlen(s);
    str=new char[len+1];
    strcpy(str,s);
    return *this;
}
char & String::operator[](int i){
    return str[i];
}
const char & String::operator[](int i)const{
    return str[i];
}
bool operator<(const String&st1,const String &st2){
    return (strcmp(st1.str,st2.str)<0);
}
bool operator>(const String&st1,const String &st2){
    return st2<st1;
}
bool operator==(const String&st1,const String &st2){
    return (strcmp(st1.str,st2.str)==0);
}
ostream & operator<<(ostream& os,const String &st){
    os<<st.str;
    return os;
}
istream & operator>>(istream& is,String &st){
    char temp[String::CINLIM];
    is.get(temp,String::CINLIM);
    if(is)
        st=temp;                //使用了const char* 参数的重载运算符
    while(is&&is.get()!='\n')   //吸收多余字符
        continue;
    return is;
}
//成员函数版本的+运算符重载,
String& String::operator+(const String &st){
    int totallen=len+st.len;
    char *temp=new char[totallen+1];        //先合成一个
    memcpy(temp,str,len);
    memcpy(temp+len,st.str,st.len);
    temp[totallen]='\0';
    delete[] str;
    str=new char[totallen+1];
    strcpy(str,temp);
    delete[] temp;
    len=totallen;                           //注意更新字符串长度
    return *this;
}
//友元函数版本的+运算符重载,处理办法类似于成员函数版本
String& operator+(const char* str,String &st){
    int length=strlen(str);
    int totallen=length+st.len;
    char *temp=new char[totallen+1];
    memcpy(temp,str,length);
    memcpy(temp+length,st.str,st.len);
    temp[totallen]='\0';
    delete[] st.str;
    st.str=new char[totallen+1];
    strcpy(st.str,temp);
    delete[] temp;
    st.len=totallen;
    return st;
}
void String::Stringlow(){
    for(int i=0;i<len;i++)
        str[i]=tolower(str[i]);
}                   
void String::Stringup(){
    for(int i=0;i<len;i++)
        str[i]=toupper(str[i]);
}                    
int String::has(char ch)const{
    int cnt=0;
    for(int i=0;i<len;i++)
        if(str[i]==ch) cnt++;
    return cnt;
}             
//******************测试函数*************************
int main(){
    String s1(" and I am a C++ student.");
    String s2="Please enter your name: ";
    String s3;
    cout<<s2;
    cin>>s3;
    s2="My name is "+s3;
    cout<<s2<<".\n";
    s2=s2+s1;
    s2.Stringup();
    cout<<"The string\n"<<s2<<"\ncontains "<<s2.has('A')
        <<" 'A' characters in it.\n";
    s1="red";
    String rgb[3]={String(s1),String("green"),String("blue")};
    cout<<"Enter the name of a primary color for mixing light: ";
    String ans;
    bool success=false;
    while(cin>>ans){
        ans.Stringlow();
        for(int i=0;i<3;i++){
            if(ans==rgb[i]){
                cout<<"That's right!\n";
                success=true;
                break;
            }
        }
        if(success)
            break;
        else
            cout<<"Try again!\n";
    }
    cout<<"Bye\n";
    return 0;
}

3

题目

  新编写程序清单10.7和程序清单10.8描述的Stock类,使之使用动态分配的内存,而不是string类对象来存储股票名称。另外,使用重载的operator<<()定义代替show()成员函数。再使用程序清单10.9测试新的定义程序。

题解

#include<iostream>
#include<cstring>
class Stock{
private:
    enum{LEN=100};
    char* company;
    long shares;
    double share_val;
    double total_val;
    void set_tot(){total_val=share_val*shares;}
public:
    Stock();
    Stock(const char* co,long n=0,double pr=0.0);
    ~Stock();
    void buy(long num,double price);
    void sell(long num,double price);
    void update(double price);
    friend std::ostream& operator<<(std::ostream &os,const Stock& s);
    const Stock&topval(const Stock& s)const;
};
//默认构造函数
Stock::Stock(){
    company=nullptr;
    shares=0;
    share_val=0.0;
    total_val=0.0;
}
//重载的构造函数
Stock::Stock(const char* co,long n,double pr){
    int len=std::strlen(co);
    company=new char[len+1];
    std::strcpy(company,co);
    if(n<0){
        std::cout<<"Number of shares can't be negative; "
                 <<company<<" shares set to 0\n";
        shares=0;
    }
    else
        shares=n;
    share_val=pr;
    set_tot();
}
//析构函数
Stock::~Stock(){
    delete[] company;
}
void Stock::buy(long num,double price){
    if(num<0){
        std::cout<<"Number of shares purchased can't be negetive."
                 <<"Transaction is borted.\n";
    }
    else{
        shares+=num;
        share_val=price;
        set_tot();
    }
}
void Stock::sell(long num,double price){
    using std::cout;
    if(num<0){
        cout<<"Number of shares sold can't be negative "
            <<"Transaction is aborted\n";
    }
    else if(num>shares){
        cout<<"You can't sell more than you hav! "
            <<"Transaction is aborted.\n";
    }
    else{
        shares-=num;
        share_val=price;
        set_tot();
    }
}
void Stock::update(double price){
    share_val=price;
    set_tot();
}
std::ostream& operator<<(std::ostream &os,const Stock& s){
    using std::ios_base;
    ios_base::fmtflags orig=os.setf(ios_base::fixed,ios_base::floatfield);
    std::streamsize prec=os.precision(3);
    os<<"Company: "<<s.company
        <<"  Shares: $"<<s.shares<<"\n"
        <<"  Shares Price: $"<<s.share_val;
    os.precision(2);
    os<<"  Total Worth: $"<<s.total_val<<"\n";
    os.setf(orig,ios_base::floatfield);
    os.precision(prec);
    return os;
}
const Stock&Stock::topval(const Stock& s)const{
    if(s.total_val>total_val)
        return s;
    else
        return *this;
}
const int STKS=4;
//主函数
int main(){
    Stock stocks[STKS]={
        Stock("NanoSmart",12,20.0),
        Stock("Boffo Objects",200,2.0),
        Stock("Monolithic Obelisks",130,3.25),
        Stock("Fleep Enterprises",60,6.5),
    };
    std::cout<<"Stock holdings:\n";
    int st;
    for(st=0;st<STKS;st++)
        std::cout<<stocks[st];
    const Stock *top=&stocks[0];
    for(st=1;st<STKS;st++)
        top=&top->topval(stocks[st]);
    std::cout<<"\nMost valueable holding:\n"<<*top;
    return 0;
}

4

题目

  请看下面程序清单10.10定义的Stack类的变量:

typedef unsigned long Item;
class Stack{
private:
    enum{MAX=10};
    Item * pitems;
    int size;
    int top;
public:
    Stack(int n=MAX);
    Stack(const Stack &st);
    ~Stack();
    bool isempty()const;
    bool isfull()const;
    bool push(const Item &item);
    bool pop(Item &item);
    Stack& operator=(const Stack &st);
};

  正如私有成员表明的,这个类使用动态分配的数组来保存栈项。请重新编写方法,以适应这种新的表示法,并编写-一个程序来演示所有的方法,包括复制构造函数和赋值运算符。

题解

#include<iostream>
#include<cctype>
typedef unsigned long Item;
class Stack{
private:
    enum{MAX=10};
    Item * pitems;
    int size;
    int top;
public:
    Stack(int n=MAX);
    Stack(const Stack &st);
    ~Stack();
    bool isempty()const;
    bool isfull()const;
    bool push(const Item &item);
    bool pop(Item &item);
    Stack& operator=(const Stack &st);
};
Stack::Stack(int n){
    pitems=new Item[n];
    size=n;
    top=0;
}
Stack::Stack(const Stack &st){
    pitems=new Item[st.size];
    for(int i=0;i<st.size;i++)
        pitems[i]=st.pitems[i];
    size=st.size;
    top=st.top;
}
Stack::~Stack(){
    delete[] pitems;
}
bool Stack::isempty()const{
    return top==0;
}
bool Stack::isfull()const{
    return top==size;
}
bool Stack::push(const Item &item){
    if(top<size){
        pitems[top++]=item;
        return true;
    }
    else
        return false;
}
bool Stack::pop(Item &item){
    if(top>0){
        item=pitems[--top];
        return true;
    }
    else
        return false;
}
Stack& Stack::operator=(const Stack &st){
    pitems=new Item[st.size];
    for(int i=0;i<st.size;i++)
        pitems[i]=st.pitems[i];
    size=st.size;
    top=st.top;
    return *this;
}
int main(){
    using namespace std;
    Stack st;
    Stack last_st;
    char ch;
    unsigned long po;
    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 number to add: ";
                      cin>>po;
                      if(st.isfull())
                        cout<<"stack already full\n";
                      else
                        st.push(po);
                      break;
            case 'P':
            case 'p': if(st.isempty())
                        cout<<"Stack already empty\n";
                      else{
                          st.pop(po);
                          cout<<"PO #"<<po<<" popped\n";
                      } 
                      break;
        }
        last_st=st;
        cout<<"Please enter A to add a purchase order,\n"
            <<"P to process a PO, or Q to quit.\n";
    }
    Stack last_st_cpoy(last_st);
    if(!last_st.isempty()){
        cout<<"Last stack contains(from top to bottom):\n";
        while(!last_st.isempty()){
            Item temp;
            last_st.pop(temp);
            cout<<temp<<" ";
        }
    }
    cout<<"\n";
    cout<<"Bye\n";
    return 0;
}

5

题目

  Heather银行进行的研究表明,ATM客户不希望排队时间不超过1分钟。使用程序清单12.10中的模拟,找出要使平均等候时间为1分钟,每小时到达的客户数应为多少(试验时间不短于100小时)?

题解

//使用queue.cpp测试即可,没有固定条件(队列大小),无法有唯一结果

6

题目

  Heather银行想知道,如果再开设一台ATM,情况将如何。请对模拟进行修改,以包含两个队列。假设当第一台ATM前的排队人数少于第二台ATM时,客户将排在第一队,否则将排在第二队。然后再找出要使平均等候时间为1分钟,每小时到达的客户数应该为多少(注意,这是一个非线性问题,即将ATM数量加倍,并不能保证每小时处理的客户数量也翻倍,并确保客户等候的时间少于1分钟)?

题解

// 没有固定条件(队列大小),无法有唯一结果

当珍惜每一片时光~