[C++ Primer Plus] 第10章、对象和类(二)课后习题

1.

bank.h

#include <string>
using namespace std;

class BankAccount        
{
private:
    std::string m_name;//若是不用命名空间的话,就需要加std::
    string m_id;
    double m_money;
public:
    BankAccount();
    BankAccount(const string & name,const string & id,double money=0.0);
    void show() const;
    void add(double money);
    void sub(double money);
};    

bank.cpp

#include <iostream>
#include "bank.h"

//构造函数
BankAccount::BankAccount(){
    m_name = "";  
    m_id = "";  
    m_money = 0.0;  
}
BankAccount::BankAccount(const string & name,const string & id,double money){
    m_name = name;  
    m_id = id;  
    m_money = money;  
}

void BankAccount::show() const{
    ios_base::fmtflags orig=cout.setf(ios_base::fixed,ios_base::floatfield);//设置cout对象的一个标记,命令cout使用定点表示法
    streamsize prec=cout.precision(2);
    cout<< "Name: " << m_name << "    ID: " << m_id << "    Money: " << m_money << endl; //因为bank.h中已经声明了命名空间,所以不需要加std::
}
void BankAccount::add(double money){
    m_money += money;  
}
void BankAccount::sub(double money){
    m_money -= money;
}

main.cpp

#include "bank.h"

void main(){
    BankAccount a("MR.Zhang","20135908",8888888.88);
    a.show();
    a.add(88888.88);
    a.show();
    a.sub(88888.88);
    a.show();
    system("pause");
}


 

//person.h
#include <string>  
  
class Person {  
private:  
    static const int LIMIT = 25;  
    std::string lname;  
    char fname[LIMIT];  
public:  
    Person() { lname = ""; fname[0] = '\0'; }  //无参数
    Person(const std::string &ln, const char *fn = "Heyyou");  //两参数
    void Show() const;  
    void FormalShow() const;  
};  

//person.cpp
#include <iostream>
#include "Person.h"

Person::Person(const std::string & ln, const char *fn)  
{  
    lname = ln;  
    strncpy_s(fname, fn ,24);  //fname的长度为25 
}  
void Person::Show() const  
{  
    std::cout << fname << " " << lname << std::endl;  
}  
  
void Person::FormalShow() const  
{  
    std::cout << lname << ", " << fname << std::endl;  
}  

//main.cpp
#include "person.h"

void main(){
    Person one;  
    Person two("Smythecraft");  
    Person three("Dimwiddy", "Sam");  
    one.Show();  
    one.FormalShow();  
    two.Show();  
    two.FormalShow();  
    three.Show();  
    three.FormalShow(); 
    system("pause");
}

前两行的显示:one为空,没有输出,FormalShow有一个逗号


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

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

这两题参考http://blog.csdn.net/qq20004604/article/details/50540039  或者   http://blog.csdn.net/acm_yuuji/article/details/47374799


 

5.考虑下面的结构声明:
struct customer {

  char fullname[35];

  double payment;

};

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

//stack.h
struct customer{
    char fullname[35];
    double payment;
};
typedef customer Item;

class Stack        //类声明
{
private:
    double total; 
    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.cpp
#include <iostream>
#include "stack.h"

//构造函数
Stack::Stack(){
    top=0;
    total=0;
}

bool Stack::isempty() const{
    return top==0;//top为0返回true,反之为false
}
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];
        total += item.payment;  
        std::cout << "总共已取出" << total << "" << std::endl;  
        return true;
    }else
        return false;
}

//main.cpp
#include<iostream>
#include<cctype>
#include "stack.h"
using namespace std;

void main(){
    cout.setf(ios_base::fixed);  
    cout.precision(2);  //设置输出保留两位小数
    Stack st;//创建对象储物柜  
    customer one;
    char ch;
    cout<<"Enter A to save money, P to withdraw money, 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':
            if(st.isfull())//该方法判断:如果满了(top等于MAX)返回true,没满返回false
                cout<<"Stack already full\n";
            else{
                cout << "请输入存钱的人的名字:";  
                cin.getline(one.fullname,34);  
                cout << "请输入要存多少钱:";  
                cin >> one.payment; 
                cin.sync(); //清除输入缓存,防止干扰  
                if (st.push(one))  
                    cout << "存放成功!" << one.fullname << " 共计 " << one.payment << " 元钱已经被存进来啦!" << endl;  
                else  
                    cout << "由于某种未知的原因,存放失败了。。。。" << endl;  
            }
            break;
        case 'P':
        case 'p':
            if(st.isempty())
                cout<<"Stack already empty\n";
            else{
                st.pop(one);
            }
            break;
        }
        cout<<"Enter A to save money, P to withdraw money, Q to quit.\n";
    }
    system("pause");
}


//1.h
class Move  
{  
private:  
    double x;  
    double y;  
public:  
    Move(double a = 0, double b = 0);   //set x,y to a,b  
    void showmove()const;   //shows current x,y values  
    Move add(const Move & m) const; //这个函数将被调用对象m的x和y值与自己的x,y值相加,并得到2个新值,然后创建一个使用新的x、y值的move对象,并将增加后的x、y值赋给她,然后将这个新对象作为返回值  
    void reset(double a = 0, double b = 0); //resets x,y to a,b  
};  

//1.cpp
#include <iostream>
#include "1.h"

Move::Move(double a, double b){
    x = a;  
    y = b; 
}

void Move::showmove()const{
    std::cout << "x = " << x << ", y = " << y << std::endl;  
}

Move Move::add(const Move & m) const{
    Move q(this->x + m.x, this->y + m.y);  
    return q;  
}

void Move::reset(double a , double b ){
    x = a;  
    y = b; 
}

//main.cpp
#include<iostream>
#include "1.h"

void main(){
    Move m,n(1.5,2.5);
    m.showmove();
    m=m.add(n);
    m.showmove();
    m.reset();
    m.showmove();
    system("pause");
}


7.Betelgeusean plorg有这些特征。

数据:

①plorg的名称不超过19个字符;

②plorg有满意指数(CI),这是一个整数。

操作:

①新的plorg将有名称,其CI值为50;

②plorg的CI可以修改;

③plorg可以报告其名称和CI;

④plorg的默认名称为“Plorga”。

请编写一个Plorg类声明(包括数据成员和成员函数原型)来表示plorg,并编写成员函数的函数定义。然后编写一个小程序,以演示Plorg类的所有特性。

//1.h
class Plorg  
{  
private:  
    char m_name[20];  
    int  m_CI;  
public:  
    Plorg(char * name = "Plorga", int CI = 50);  
    void show()const;   
    void setName(const char *name);  
    void setCI(const int CI);
};  

//1.cpp
#include <iostream>
#include "1.h"

Plorg::Plorg(char * name, int CI){
    strncpy_s(m_name, name,19);  
    m_CI = CI;  
}
       
void Plorg::setName(const char *name){
    strncpy_s(m_name, name,19);  
} 
void Plorg::setCI(const int CI){
    m_CI = CI; 
}
void Plorg::show()const{
    std::cout << "name = " << m_name << ", CI = " << m_CI << std::endl;  
}

//main.cpp
#include<iostream>
#include "1.h"

void main(){
    Plorg p;
    p.show();
    p.setName("Jany");
    p.setCI(49);
    p.show();
    system("pause");
}


//list.h
#include <stdlib.h>    //包含NULL的定义
typedef int Item;  
  
class List  
{  
private:  
    static const int LIMIT  = 5;  
    Item items[LIMIT];  
    int top;  
public:  
    List() { top = 0; }   //默认构造函数  
    bool push(const Item); //添加数据项  
    bool isempty()const;    //确定是否为空  
    bool isfull()const;        //是否为满  
    void visit(void(*pf)(Item &m)); //显示每个数据项,并执行某种操作,具体是哪种,根据指针指向的函数而定 
};  

//list.cpp
#include "List.h"  
  
bool List::push(const Item item)  
{  
    if (isfull() == true)  
        return false;  
    items[top++] = item;  
    return true;  
}  
  
bool List::isempty() const  
{  
    return top == 0 ? true : false;  
}  
  
bool List::isfull() const  
{  
    return top == LIMIT ? true : false;  
}  
  
void List::visit(void(*pf)(Item &item))  
{  
    for (int i = 0; i < top; ++i)  
        (*pf)(items[i]);  
} 

//main.cpp
#include<iostream>
#include "list.h"

void Print(Item &item)  
{  
    std::cout << item << std::endl;  
} 
void main(){
    List l;  
    l.push(1);  
    l.push(2);  
    l.push(3);  
    l.push(4);  
    if(l.isempty())
        std::cout << "isEmpty? " << "Empty" << std::endl;
    else
        std::cout << "isEmpty? " << "Not Empty" << std::endl;
    if(l.isfull())
        std::cout << "isFull? " << "Full" << std::endl;
    else
        std::cout << "isFull? " << "Not Full" << std::endl;
    void(*pf)(Item &item);  
    pf = Print;  //或者    void(*pf)(Item &item) = Print
    l.visit(pf); 
    system("pause");
}

总结:

①在类中以函数指针作为参数的时候,纠结了很久,查了别人的答案才明白。

例如:void visit( void (*pf)(Item& m) );

这个的意思是,visit函数中,使用函数指针pf作为参数。

在调用visit函数时,哪个函数名作为参数放在里面,那么pf指针就指向哪个函数(前提是类型相同)。

因为指针作为参数,所以参数有点类似( char* pa)这样的意思,char*表示pa是char类型的指针,但不是说char*是参数,所以函数指针作为参数时,重点是pf,而不是外面那个修饰pf的。

可以使用typedef void (*PP)(Item &m);将PP作为这个的别名,于是可以改为void visit(PP pf);这样。

因为没把函数指针学透,纠结了很久,写完代码才想明白。

因为pf是函数指针,所以函数内部的pf(items[i])是将items[i]作为参数给pf指向的函数。例如当show函数作为参数给visit时,这里相当于show(items[i])。

版权声明:出处http://blog.csdn.net/qq20004604

 

posted @ 2017-10-29 14:12  进击的小猴子  阅读(1327)  评论(0编辑  收藏  举报