• [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] = ''; }  //无参数
        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.
    ";
        while (cin>>ch&&toupper(ch)!='Q')
        {
            while(cin.get()!='
    ')//如果不是换行就继续
                continue;
            if (!isalpha(ch))//如果不是字母就继续
            {
                cout<<'a';
                continue;
            }
            switch (ch)
            {
            case 'A':
            case 'a':
                if(st.isfull())//该方法判断:如果满了(top等于MAX)返回true,没满返回false
                    cout<<"Stack already full
    ";
                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
    ";
                else{
                    st.pop(one);
                }
                break;
            }
            cout<<"Enter A to save money, P to withdraw money, Q to quit.
    ";
        }
        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
  • 相关阅读:
    linux 之 系统监控
    Spring Cloud Eureka 常用配置及说明
    mysql的事务隔离级别
    什么场景中会用到java多线程(转)
    springboot配置druid连接池
    MyBatis标签详解(转)
    关于@JsonSerialize注解的使用方法
    layer绑定回车事件(转)
    php7+apache2.4配置
    Eclipse创建Maven项目不支持el表达式的解决方式
  • 原文地址:https://www.cnblogs.com/little-monkey/p/7748044.html
Copyright © 2020-2023  润新知