Thursday 22 August 2019

Chapter 9 // Exercise 16 - 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 16



Define an input operator (>>) that reads monetary amounts with currency denominations, such as USD1.23 and DKK5.00, into a Money variable. Also define a corresponding output operator.

main.cpp

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

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

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

 Money amount2(c_USD, 786.789);
 amount1.printMoney();

 //read in new money
 cin >> amount1;
 cin >> amount2;

 //print new amounts
 cout << amount1 << endl;
 cout << amount2 << endl;

 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 <string>
#include <iostream>
#include <iomanip>
#include <conio.h>

using namespace std;

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

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

 void printMoney();

 Currencies getCurrency() { return m_currency; }
 void changeCurrency(Currencies currency) { m_currency = 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);
istream& operator>>(istream& is, 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() {}

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 << fixed << setprecision(2) << "\n£" << money.getInputMoney() << endl;
  break;
 case c_USD:
  return os << fixed << setprecision(2) << "\n$" << money.getInputMoney() << endl;
  break;
 default:
  return os << "Bad output";
  break;
 }
}

//read money into a Money variable
istream& operator>>(istream& is, Money& money)
{
 cout << "Please enter currency, followed by amount. For example GBP3.45" << endl;
 cout << "Currencies available: GBP || USD" << endl;

 string getMoney;
 cin >> getMoney;

 string denomination, amount;
 double mon;

 for (int i = 0; i < getMoney.size(); ++i)
 {
  if (i < 3)
   denomination += getMoney[i];
  else
   amount += getMoney[i];
 }

 //convert string to double
 mon = stod(amount);

 //update money variable
 if (denomination == "GBP")
 {
  money = Money(c_GBP, mon);
  money.changeCurrency(c_GBP);
 }
 else if (denomination == "USD")
 {
  money = Money(c_USD, mon);
  money.changeCurrency(c_USD);
 }
 else
 {
  cout << "bad input.";
 }

 return is;
}

My example is omitting some error checking due to time constraints so don't put in any illegal values otherwise it'll break however it does what he has asked for. When using cin >> with a Money variable it allows the user to input a new monetary value as well as change the currency. The << was already implemented in the last exercise. I also learnt in this exercise that there is a whole load of functions in the standard library for converting strings to almost any type of decimal. Bless the standard library.

1 comment:

  1. Thank you for your sharing and helpful explanation!

    ReplyDelete