C++ Premier Plus 6th edition - Programming excercise - Chapter11 - 5

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_42787086/article/details/84026422

这道题里,用switch和while配合时,着实花了不少时间,还是使用不熟练所致。
排除非法输入(非int)和非1、2、3的用法,尽量做到精简。

实现1个需求的方法有无数种,代码也有无数种,但尽量用注释记录自己当时的思路,回头看的时候可以找到不完善的地方进一步修改和调整。

stonewt.h

// stonewt.h -- definition for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
class Stonewt
{
private:
    enum {Lbs_per_stn = 14};      // pounds per stone

    // Newly added:3 modes
    enum Mode {STONE,INT_PDS,FLOAT_PDS};
    Mode mode;// 3 modes

    int stone;                    // whole stones
    double pds_left;              // fractional pounds
    double pounds;                // entire weight in pounds
    // Newly added:
    /*
    relationship understanding,eg:
    15.5 pounds == 1 stone 1.5 pds_left
    */

public:
    Stonewt(double lbs);          // constructor for double pounds
    Stonewt(int stn, double lbs); // constructor for stone, lbs
    Stonewt();                    // default constructor
    ~Stonewt();

    /*
    Newly added: remove below 2 methods
    void show_lbs() const;        // show weight in pounds format
    void show_stn() const;        // show weight in stone format
    */

    // reload operator + - *
    Stonewt operator+(Stonewt&obj) const;
    Stonewt operator-(Stonewt&obj) const;
    Stonewt operator*(double n) const;

    // set mode to STONE,POUNDS,PDS_LEFT
    void setMode() ;

    // friend:
    // reload operator<<
    friend std::ostream& operator<<(std::ostream&os,Stonewt& obj);
    // reload operator*(double,objective),change position
    friend Stonewt operator*(double n, const Stonewt& obj) ;

};
#endif

/*
data compeonents are same,state member is supposed to control show(),which appears
as reloaded operator<<.
*/

stonewt.cpp

// stonewt.cpp -- Stonewt methods
#include <iostream>
using std::cout;
using std::cin;

#include "stonewt.h"
#include<cstdlib>

// construct Stonewt object from double value
Stonewt::Stonewt(double lbs)
{
    stone = int (lbs) / Lbs_per_stn;    // integer division
    pds_left = int (lbs) % Lbs_per_stn + lbs - int(lbs);
    pounds = lbs;

    // Newly added,set default form for <<
    mode = STONE;
}

// construct Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs)
{
    stone = stn;
    pds_left = lbs;
    pounds =  stn * Lbs_per_stn +lbs;

    // Newly added,set default form for <<
    mode = STONE;
}

Stonewt::Stonewt()          // default constructor, wt = 0
{
    stone = pounds = pds_left = 0.0;
}

Stonewt::~Stonewt()         // destructor
{
}

// Newly added: reload operator + - *
// the class Stonewt doesn't have methods to set
// values of data components automatically,so have to create new objective
Stonewt Stonewt::operator+(Stonewt&obj) const
{
    double temp = pounds + obj.pounds;
    return Stonewt(temp);
}

Stonewt Stonewt::operator-(Stonewt&obj) const
{
    double temp = pounds - obj.pounds;
    return Stonewt(temp);
}

Stonewt Stonewt::operator*(double n) const
{
    double temp = pounds*n;
    return Stonewt(temp);
}


/*
regarding mode, have easy way to realize
void stone_mode(){mode = STONE;}
void intPDS_mode(){mode = INT_PDS;}
void fltPDS_mode(){mode = FLOAT_PDS;}
but here just want to pratise the use of switch
*/
// have to set default mode before user choose
void Stonewt::setMode()
{
    cout << "Which mode would you like?\n"
         << "(input: 1 for stone form, 2 for interger pounds form, 3 for floating-points form.\n";
    int x;

    // in case user's invalid input cause program stuck(eg, a,/,55ss,aa55,9)
    // will still go into loop and get prompt
    cin >> x;
    while (cin.fail() || !(x == 1 || x == 2 || x == 3))
    {
        cout << "Invalid input, only number 1/2/3 is allowed. Pls enter again: ";
        cin.clear();
        while (cin.get() != '\n')//clear input queue
            continue;
        cin >> x;
    }

    switch (x)
    {
    case 1:
        mode = STONE;
        break;
    case 2:
        mode = INT_PDS;
        break;
    case 3:
        mode = FLOAT_PDS;
        break;
    }
}

// Newly added: object is interpreted in stone form, integer pounds form,
// or floating - point pounds form.

// friend defination
std::ostream& operator<<(std::ostream&os, Stonewt& obj)
{
    // can be (obj.mode == obj.STONE)?
    if (obj.mode == Stonewt::STONE)
    {
        os << obj.stone << " stone, " << obj.pds_left << " pounds\n";
    }
    else if (obj.mode == Stonewt::INT_PDS)
    {
        os << (int)obj.pounds << " pounds\n";
    }
    else if (obj.mode == Stonewt::FLOAT_PDS)
    {
        os << obj.pounds << " pounds\n";
    }
    return os;
}

Stonewt operator*(double n, const Stonewt& obj)
{
    // revolk member function operator*(double n)
    return obj * n;
}

main.cpp

// main
#include<iostream>
#include"stonewt.h"
using std::cout;

int main()
{
    // use 2 constructors
    Stonewt s1(2000.3);
    Stonewt s2(19, 14.5);

    Stonewt s3(0);// empty objective

    // use reloaded operator + - *
    s3 = s1 + s2;
    cout << "s1 + s2 result: " << s3 << std::endl;

    s3 = s1 - s2;
    cout << "s1 - s2 result: " << s3 << std::endl;

    s3 = s1 * 5.5;
    cout << "s1 * 5.5 result: " << s3 << std::endl;

    // use friend oerator*
    s3 = 5.5*s1;

    // use setMode(),from INT_PDS
    cout << "Now shows s3 result in another 2 forms.\n";
    s3.setMode();
    cout << "5.5*s1 result: " << s3 << std::endl;

    // use setMode(),form FLOAT_PDS
    s3.setMode();
    cout << "5.5*s1 result: " << s3 << std::endl;

    std::cin.get();
    std::cin.get();
}

猜你喜欢

转载自blog.csdn.net/weixin_42787086/article/details/84026422