1. 程式人生 > >C++ Premier Plus 6th edition - Programming excercise - Chapter11 - 5

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

這道題裡,用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();
}