Wednesday 21 August 2019

Chapter 9 // Exercise 15 - Principles & Practice Using C++

In this exercise I am using Visual Studio Community 2017 and the header file "std_lib_facilities.h" which can be found here:

http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h


Chapter 9 // Exercise 15



Refine the Money class by adding a currency (given as a constructor argument). Accept a floating-point initializer as long as it can be exactly represented as a long int. Don't accept illegal operations. For example, Money*Money doesn't make sense, and USD1.23+DKK5.00 makes sense only if you provide a conversion table defining the conversion factor between U.S. dollars (USD) and Danish kroner (DKK).

...I literally have no idea what he wants me to do here. So we add a currency in the constructor, say GBP as a string along with a floating-point value. We've already been doing that but now we have to to do a check to ensure that it will fit in a long int. A long int is 32 bits in size and a double is 64 bits. (If anyone is interested, in a programming interview I was asked about the size of a struct and it contained all the fundamental types, so it's worth learning the sizes of each type). A float is 32 bits so perhaps we should change m_dollars to a float instead. The worst that would happen if we didn't is that we would lose some bits as they would get truncated to fit. I don't understand what he means by illegal operations though. Does he mean, don't allow Money*Money in the initialiser? It wouldn't compile anyway in the code as there is no definition for it. And for USD1.23+DKK5.00 where is this called? By the programmer writing the code or is it an argument passed to the program via input from the user? If it was the latter, I suppose you would take it in as a string and parse each value, then pass the currency and value to the money class to be constructed with that value. You can construct new classes at run time but it's far beyond what's been taught in the book so far. This is not well constructed exercise.

main.cpp

//----------------------------------//
// main.cpp
//----------------------------------//

//INCLUDES//
#include "moneyClass.h"

int main()
{
 Money gbp(c_GBP, 3.34);
 gbp.printMoney();

 Money usd(c_USD, 786.789);
 usd.printMoney();

 gbp + usd;
 usd + gbp;

 cout << "\nPress any key to quit...";
 _getch();

 return 0;
}

moneyClass.h

//----------------------------------//
// moneyClass.h
//----------------------------------//
// for calculations involving money
//----------------------------------//
#ifndef _MONEYCLASS_H_
#define _MONEYCLASS_H_

//INCLUDES//
#include <iostream>
#include <iomanip>
#include <conio.h>

using namespace std;

//----------------------------------//
// ENUM: Currencies
//----------------------------------//
enum Currencies
{
 c_GBP,
 c_USD
};

//----------------------------------//
// CLASS: Money
//----------------------------------//
class Money
{
public:
 Money(Currencies currency, float amount);
 ~Money();

 void printMoney();

 Currencies getCurrency()    { return m_currency; }
 long int   getOutPutMoney() { return m_outputMoney; }
 double     getInputMoney()  { return m_inputMoney; }

private:
 //variables//
 Currencies m_currency;
 long int m_outputMoney; //cents
 double m_inputMoney; //dollars

};

//OPERATOR OVERLOADS//
void operator+(Money& money1, Money& money2);
ostream& operator<<(ostream& os, Money& money);

#endif // !_MONEYCLASS_H_


moneyClass.cpp

//----------------------------------//
// moneyClass.cpp
//----------------------------------//
// for calculations involving money
//----------------------------------//

//INCLUDES//
#include "moneyClass.h"

//VARIABLES//
double gbp2usd = 1.26;
double usd2gbp = 0.79;

Money::Money(Currencies currency, float amount) 
{
 m_currency = currency;
 m_inputMoney = amount;
}

Money::~Money() {}

//print output as dollars
void Money::printMoney()
{
 m_outputMoney = round(m_inputMoney * 100.0f);

 switch (m_currency)
 {
 case c_USD:
  cout << "-----USD----" << endl;
  cout << "Dollars: $" << fixed << setprecision(2) << m_inputMoney << endl;
  cout << "Cents: " << fixed << setprecision(0) << m_outputMoney << endl;
  break;
 case c_GBP:
  cout << "-----GBP----" << endl;
  cout << "Pounds: £" << fixed << setprecision(2) << m_inputMoney << endl;
  cout << "Pennies: " << fixed << setprecision(0) << m_outputMoney << "p" << endl;
  break;
 default:
  cout << "Bad output";
  break;
 }
}

//OPERATOR OVERLOADS//

//add currencies together - converts money if not the same
void operator+(Money& money1, Money& money2)
{
 cout << "\n";
 if (money1.getCurrency() == money2.getCurrency())
  //currencies are the same, no conversion needed, just add
  cout << fixed << setprecision(2) << money1.getInputMoney() + money2.getInputMoney();
 else if (money1.getCurrency() == c_GBP && money2.getCurrency() == c_USD)
 {
  //return pounds
  cout << fixed << setprecision(2) << "£" << (money2.getInputMoney() * usd2gbp) + money1.getInputMoney() << endl;
 }
 else if (money1.getCurrency() == c_USD && money2.getCurrency() == c_GBP)
 {
  //return dollars
  cout << fixed << setprecision(2) << "$" << (money2.getInputMoney() * gbp2usd) + money1.getInputMoney() << endl;
 }
}

//print out money
ostream& operator<<(ostream& os, Money& money)
{
 switch (money.getCurrency())
 {
 case c_GBP:
  return os << "\n£" << money.getInputMoney() << endl;
  break;
 case c_USD:
  return os << "\n$" << money.getInputMoney() << endl;
  break;
 default:
  return os << "Bad output";
  break;
 }
}

I'm still not entirely sure if this is what he wanted us to do but it takes in a currency (and you can add more to the enum, just provide converters in moneyClass.cpp). I even added some operator overloads to print out the money and add different currencies together.

No comments:

Post a Comment