roman numerals calculator

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 10 Exercise 7
Using std_lib_facilities.h by Bjarne Stroustrup.

My project includes the following files:
p377_7_romanIntMain.cpp my main cpp file
p377_7_romanIntClass.h my roman integer class header file

p377_7_romanIntMain.cpp my main cpp file

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 10 Exercise 7

#include "p378_7_romanNumerals_class.h"

const char let = '#';
const char quitProg = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char constant = 'O';
const char reset = 'R';
const char help = 'H';

struct Token {
	char kind;
	Roman_int value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, Roman_int val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get()
{
	if (full) {
		full = false;
		return buffer;
	}

	char ch;
	cin.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		cin.get(ch);
	}

	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case 'N':
	case 'I':
	case 'V':
	case 'X':
	case 'L':
	case 'C':
	case 'D':
	case 'M':
	{
		cin.unget();
		Roman_int val;
		cin >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch;
			}
			cin.unget(); //puts the most recently read character back into the stream
			if (s == "quit") return Token(quitProg);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			if (s == "help" || s == "Help") return Token(help);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' ');
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	Roman_int value;
	bool immutable;
	Variable(string n, Roman_int v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	Roman_int get(string);
	void set(string, Roman_int);
	bool is_declared(string);
	Roman_int declare(char);
	bool is_immutable(string);
};

Token_stream ts;
Roman_int expression();
Roman_int primary();

Roman_int Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0;
}

void Symbol_table::set(string s, Roman_int d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

Roman_int Symbol_table::declare(char kind)
{
	Token t = ts.get();
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	Roman_int d = expression();
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

Symbol_table st;

Roman_int primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		Roman_int d = expression();
		t = ts.get();
		if (t.kind != ')') error("')' expected");
		return d;
	}
	case '-':
	{
		return -primary();
	}
	case '+':
	{
		return primary();
	}
	case number:
	{
		return t.value;
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
	}
	}
}

Roman_int term()
{
	Roman_int left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '*':
		{
			left = left * primary();
			break;
		}
		case '/':
		{
			Roman_int d = primary();
			if (d == Roman_int(0)) error("divide by zero");
			left = left / d;
			break;
		}
		case '%':
		{
			Roman_int i1 = left;
			Roman_int i2 = primary();
			if (i2 == Roman_int(0)) error("%: divide by zero");
			left = i1 % i2;
			break;
		}
		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

Roman_int expression()
{
	Roman_int left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left = left + term();
			break;
		}
		case '-':
		{
			left = left - term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

Roman_int statement()
{
	Token t = ts.get();
	Roman_int d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}

	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	cout << "Welcome to my calculator.\n"
		<< "Just hit enter or ; at the end of your function to calculate.\n"
		<< "Enter help or Help for help or quit to exit the program.\n";
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == help) {
			cout << "You can use / *-+operators.\n"
				<< "Declaring variables using #, for example: # x = 5.\n";
		}
		else {
			if (t.kind == quitProg) {
				return;
			}
			ts.unget(t);
			cout << result << statement() << endl;
		}
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()
try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}

p377_7_romanIntClass.h my roman integer class header file

#pragma once
//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 10 Exercise 7

#include "std_lib_facilities.h"

vector<char> roman_chars = {
	'N', 'I', 'V', 'X', 'L', 'C', 'D', 'M'
};

int roman_char_value(char ch) {
	switch (ch) {
	case 'N':
		return 0;
	case 'I':
		return 1;
	case 'V':
		return 5;
	case 'X':
		return 10;
	case 'L':
		return 50;
	case 'C':
		return 100;
	case 'D':
		return 500;
	case 'M':
		return 1000;
	default:
		return -1;
	}
}

class Roman_int {
private:
	string roman_string;
	int roman_int;
public:

	Roman_int() {};
	Roman_int(int _roman_int);
	Roman_int(string _roman_string);

	void set_values();
	void set_values(int);
	string get_string() { return roman_string; }
	int get_int() { return roman_int; }
};

//DEFAULT OVERLOAD------

Roman_int::Roman_int(int _roman_int) {
	roman_int = _roman_int;
}

Roman_int::Roman_int(string _roman_string) {
	roman_string = _roman_string;
}

//DEFAULT OVERLOAD------END


//OPERATOR OVERLOAD-------

ostream& operator<<(ostream& os, Roman_int& _roman_int) {
	os << "Roman_int conversion:\n"
		<< _roman_int.get_string()
		<< " equals " << _roman_int.get_int() << endl;
	return os;
}

Roman_int operator+(Roman_int& r1, Roman_int& r2) {
	Roman_int result(r1.get_int() + r2.get_int());
	return result;
}

Roman_int operator-(Roman_int& r1, Roman_int& r2) {
	Roman_int result(r1.get_int() - r2.get_int());
	return result;
}

Roman_int operator-(Roman_int& r1) {
	Roman_int result(-r1.get_int());
	return result;
}

Roman_int operator*(Roman_int& r1, Roman_int& r2) {
	Roman_int result(r1.get_int() * r2.get_int());
	return result;
}

Roman_int operator/(Roman_int& r1, Roman_int& r2) {
	Roman_int result(r1.get_int() / r2.get_int());
	return result;
}

Roman_int operator%(Roman_int& r1, Roman_int& r2) {
	Roman_int result(r1.get_int() % r2.get_int());
	return result;
}

bool operator==(Roman_int& r1, Roman_int& r2) {
	if (r1.get_int() == r2.get_int()) {
		return true;
	}
	else {
		return false;
	}
}

bool operator!=(Roman_int& r1, Roman_int& r2) {
	if (r1.get_int() != r2.get_int()) {
		return true;
	}
	else {
		return false;
	}
}

bool operator<(Roman_int& r1, Roman_int& r2) {
	if (r1.get_int() < r2.get_int()) {
		return true;
	}
	else {
		return false;
	}
}

bool operator>(Roman_int& r1, Roman_int& r2) {
	if (r1.get_int() > r2.get_int()) {
		return true;
	}
	else {
		return false;
	}
}

bool operator<=(Roman_int& r1, Roman_int& r2) {
	if (r1.get_int() <= r2.get_int()) {
		return true;
	}
	else {
		return false;
	}
}

bool operator>=(Roman_int& r1, Roman_int& r2) {
	if (r1.get_int() >= r2.get_int()) {
		return true;
	}
	else {
		return false;
	}
}

//OPERATOR OVERLOAD-------END


//READ------

bool read_roman_string(string& _value) {
	string _value_temp;
	if (cin >> _value_temp) {
		_value = _value_temp;
		return true;
	}
	else {
		return false;
	}
}

//CHECK VALIDITY------

bool check_string_validity(string& _value) {
	if (_value.size() == 1) {
		cout << "Checking validity of roman char... ";
	}
	else {
		cout << "Checking validity of roman string... ";
	}

	int size = int(_value.size());
	vector<int> invalid_index;

	for (int i = 0; i < size; i++) {
		int check = 0;
		for (int j = 0; j < roman_chars.size(); j++) {
			if (roman_chars[j] == _value[i]) {
				check++;
			}
		}
		if (check == 0) {
			invalid_index.push_back(i);
		}
	}

	if (invalid_index.size() != 0) {
		cout << "Invalid char: ";
		for (int i = 0; i < invalid_index.size(); i++) {
			cout << _value[invalid_index[i]] << " ";
		}
		cout << endl;
		return false;
	}
	else {
		if (_value.size() == 1) {
			cout << "Valid roman char." << endl;
			return true;
		}
		else {
			cout << "Valid roman string." << endl;
			return true;
		}
	}
}

bool check_char_validity(char& _value) {
	cout << "Checking validity of roman char... ";

	int check = 0;
	for (int j = 0; j < roman_chars.size(); j++) {
		if (roman_chars[j] == _value) {
			check++;
		}
	}
	if (check == 0) {
		cout << "Invalid char: " << _value << endl;
		return false;
	}
	else {
		cout << "Valid roman char." << endl;
	}
}

//CHECK COUNT------

bool check_char_count(string& _value) {
	cout << "Checking number of roman chars... ";

	int size = _value.size();
	vector<int> counter(roman_chars.size(), 0);

	for (int i = 0; i < size; i++) {
		for (int j = 0; j < roman_chars.size(); j++) {
			if (_value[i] == roman_chars[j]) {
				counter[j]++;
			}
		}
	}

	int check = 0;
	for (int i = 0; i < roman_chars.size(); i++) {
		if (counter[i] > 1 && (roman_chars[i] == 'V' || roman_chars[i] == 'L' || roman_chars[i] == 'D')) {
			cout << "Invalid number of " << roman_chars[i] << "." << endl;
			check++;
		}
		else if (counter[i] > 3 && (roman_chars[i] == 'I' || roman_chars[i] == 'X' || roman_chars[i] == 'C' || roman_chars[i] == 'M')) {
			cout << "Invalid number of " << roman_chars[i] << "." << endl;
			check++;
		}
	}
	if (check == 0) {
		if (_value.size() == 1) {
			cout << "It is a single char." << endl;
		}
		else {
			cout << "Valid number of chars." << endl;
		}
		return true;
	}
	else {
		return false;
	}
}

//STRING TO INT-------

void decompose_roman_string(string& _value, int& _digit) {
	cout << "Decomposing roman string... ";

	int resulting_val = 0;
	int size = _value.size();
	int check = 0;

	//fill vector
	vector<int> value_ints;
	for (int i = 0; i < size; i++) {
		value_ints.push_back(roman_char_value(_value[i]));
	}

	/*
	I placed before V or X indicates one less, so four is IV (one less than five) and nine is IX (one less than ten)
	X placed before L or C indicates ten less, so forty is XL (ten less than fifty) and ninety is XC (ten less than a hundred)
	C placed before D or M indicates a hundred less, so four hundred is CD (a hundred less than five hundred) and nine hundred is CM (a hundred less than a thousand)
	*/

	if (size == 1) {
		resulting_val = value_ints[0];
	}
	else {
		for (int i = 0; i < size; i++) {
			if (_value[i] == 'I' && (_value[i + 1] == 'V' || _value[i + 1] == 'X')) {
				if (i == 0 && size == 2) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else if ((value_ints[i + 1] - value_ints[i]) < resulting_val) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else {
					cout << "Number not existing." << endl;
					check = 1;
				}
			}
			else if (_value[i] == 'X' && (_value[i + 1] == 'L' || _value[i + 1] == 'C')) {
				if (i == 0 && size == 2) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else if ((value_ints[i + 1] - value_ints[i]) < resulting_val) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else {
					cout << "Number not existing." << endl;
					check = 1;
				}
			}
			else if (_value[i] == 'C' && (_value[i + 1] == 'D' || _value[i + 1] == 'M')) {
				if (i == 0 && size == 2) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else if ((value_ints[i + 1] - value_ints[i]) < resulting_val) {
					resulting_val += (value_ints[i + 1] - value_ints[i]);
					i++;
				}
				else {
					cout << "Number not existing." << endl;
					check = 1;
				}
			}
			else {
				resulting_val += value_ints[i];
			}
		}
	}

	if (check == 0) {
		cout << "resulting value = " << resulting_val << endl;
		_digit = resulting_val;
	}
}

//SET VALUES------

void Roman_int::set_values() {
	//while (true) {
	cout << "Enter roman string or char:" << endl;
	//read roman string from user
	if (read_roman_string(roman_string)) {
		if (roman_string == "p") {
			//break;
		}
		//check if valid roman chars
		//check if valid count of chars
		else if (check_string_validity(roman_string) && check_char_count(roman_string)) {
			//decompose roman string
			decompose_roman_string(roman_string, roman_int);
			cout << "Roman_int conversion:\n"
				<< get_string()
				<< " equals " << get_int() << endl;
		}
	}
	//}
}

void Roman_int::set_values(int _val) {
	roman_int = _val;
}

istream& operator>>(istream& is, Roman_int& _roman_int) {
	// throw exception if is.bad()
	is.exceptions(is.exceptions() | ios_base::badbit);

	string s;
	char ch;

	// add characters to s until space, newline, eof or invalid character
	while (is.get(ch)) {
		if (check_char_validity(ch)) s += ch;
		else {
			is.putback(ch);
			break;
		}
	}

	// s consists only of valid characters - is it a valid Roman numeral?
	int val;
	decompose_roman_string(s, val);
	_roman_int.set_values(val);
	return is;
}
Output:
Welcome to my calculator.
Just hit enter or ; at the end of your function to calculate.
Enter help or Help for help or quit to exit the program.
> XVI - IV
Checking validity of roman char... Valid roman char.
Checking validity of roman char... Valid roman char.
Checking validity of roman char... Valid roman char.
Checking validity of roman char... Invalid char:
Decomposing roman string... resulting value = 16
Checking validity of roman char... Valid roman char.
Checking validity of roman char... Valid roman char.
Checking validity of roman char... Invalid char:

Decomposing roman string... resulting value = 4
= Roman_int conversion:
 equals 12
>

money class 1.2

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 16
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 16

#include "std_lib_facilities.h"

enum currency {
	USD, EUR, GBP
};

class Money {
public:
	long int amount;
	currency cur;

	//constructors
	Money();
	Money(double);
	Money(currency, double);

	//non-modifying operations
	long int get_amount() { return amount; }
	double get_amount_decimal();

	//modifying operations
};

Money::Money() {
	amount = 0;
	cur = USD;
}

Money::Money(double a) {
	double temp_d0 = a;
	temp_d0 *= 100;
	int temp_i = (int)temp_d0;
	double difference = temp_d0 - temp_i;
	if (difference >= 0.5) {
		temp_i++;
	}
	amount = temp_i;
	cur = USD;
}

Money::Money(currency c, double a) {
	double temp_d0 = a;
	temp_d0 *= 100;
	int temp_i = (int)temp_d0;
	double difference = temp_d0 - temp_i;
	if (difference >= 0.5) {
		temp_i++;
	}
	amount = temp_i;
	cur = c;
}

double Money::get_amount_decimal() {
	return double(amount) / 100;
}

double EURtoUSD(double d) {
	return d * 1.12;
}

double GBPtoUSD(double d) {
	return d * 1.26;
}

double USDtoEUR(double d) {
	return d * 0.89;
}

double GBPtoEUR(double d) {
	return d * 1.13;
}

double USDtoGBP(double d) {
	return d * 0.78;
}

double EURtoGBP(double d) {
	return d * 0.88;
}

Money operator+(Money & m1, Money & m2) {

	switch (m1.cur) {
	case USD: {
		switch (m2.cur) {
		case USD: {return Money(USD, m1.get_amount_decimal() + m2.get_amount_decimal()); }
		case EUR: {return Money(USD, m1.get_amount_decimal() + EURtoUSD(m2.get_amount_decimal())); }
		case GBP: {return Money(USD, m1.get_amount_decimal() + GBPtoUSD(m2.get_amount_decimal())); }
		}
	}
	case EUR: {
		switch (m2.cur) {
		case USD: {return Money(m1.get_amount_decimal() + USDtoEUR(m2.get_amount_decimal())); }
		case EUR: {return Money(m1.get_amount_decimal() + m2.get_amount_decimal()); }
		case GBP: {return Money(m1.get_amount_decimal() + GBPtoEUR(m2.get_amount_decimal())); }
		}
	}
	case GBP: {
		switch (m2.cur) {
		case USD: {return Money(GBP, m1.get_amount_decimal() + USDtoGBP(m2.get_amount_decimal())); }
		case EUR: {return Money(GBP, m1.get_amount_decimal() + EURtoGBP(m2.get_amount_decimal())); }
		case GBP: {return Money(GBP, m1.get_amount_decimal() + m2.get_amount_decimal()); }
		}
	}
	}

}

istream & operator>>(istream & is, Money & m) {
	string cur;
	char l;
	double amount;

	while (true) {
		is >> l;
		if (isalpha(l)) {
			cur += l;
		}
		else {
			if (cur == "USD" || cur == "EUR" || cur == "GBP") {
				if (cur == "USD") {
					m.cur = currency::USD;
				}
				else if (cur == "EUR") {
					m.cur = currency::EUR;
				}
				else if (cur == "GBP") {
					m.cur = currency::GBP;
				}
			}
			else {
				cout << "Invalid currency" << cur << endl;
				break;
			}

			is.putback(l);
			is >> amount;

			m = Money(m.cur, amount);
			break;
		}
	}

	return is;
}


ostream & operator<<(ostream & os, Money & m) {
	switch (m.cur) {
	case(USD):
	{
		os << "USD " << m.get_amount_decimal();
		return os;
	}
	case(EUR):
	{
		os << "EUR " << m.get_amount_decimal();
		return os;
	}
	case(GBP):
	{
		os << "GBP " << m.get_amount_decimal();
		return os;
	}
	}
}


void calculate() {

	cout << "Enter first set of money as float: " << endl;
	cout << "Supported currencies: EUR, GBP, USD," << endl;
	cout << "Format example: USD 12.235" << endl;
	Money money1;
	cin >> money1;

	cout << "Enter second set of money as float: " << endl;
	cout << "Supported currencies: EUR, GBP, USD," << endl;
	cout << "Format example: USD 12.235" << endl;
	Money money2;
	cin >> money2;
	
	Money money3 = money1 + money2;
	cout << money1 << " + " << money2 << " = ";
	cout << money3 << endl;;
}


int main()
try
{
	calculate();
	keep_window_open();
}

catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}
Output:
Enter first set of money as float:
Supported currencies: EUR, GBP, USD,
Format example: USD 12.235
USD 423.325
Enter second set of money as float:
Supported currencies: EUR, GBP, USD,
Format example: USD 12.235
EUR 544.234
USD 423.33 + EUR 544.23 = USD 1032.87
Please enter a character to exit

money class 1.1

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 15
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 15

#include "std_lib_facilities.h"

enum currency {
	USD, EUR, GBP
};

ostream & operator<<(ostream & os, currency & c) {
	if (c == USD) {
		os << "USD";
		return os;
	}
	if (c == EUR) {
		os << "EUR";
		return os;
	}
	if (c == GBP) {
		os << "GBP";
		return os;
	}
}

class Money {
public:
	long int amount;
	currency cur;

	//constructors
	Money();
	Money(double);
	Money(currency, double);

	//non-modifying operations
	long int get_amount() { return amount; }
	double get_amount_decimal();
	void read_value(bool&, currency&, double&);
	void print() { cout << cur << get_amount_decimal() << endl; }

	//modifying operations
};

Money::Money() {
	amount = 0;
	cur = USD;
}

Money::Money(double a) {
	double temp_d0 = a;
	temp_d0 *= 100;
	int temp_i = (int)temp_d0;
	double difference = temp_d0 - temp_i;
	if (difference >= 0.5) {
		temp_i++;
	}
	amount = temp_i;
	cur = USD;
}

Money::Money(currency c, double a) {
	double temp_d0 = a;
	temp_d0 *= 100;
	int temp_i = (int)temp_d0;
	double difference = temp_d0 - temp_i;
	if (difference >= 0.5) {
		temp_i++;
	}
	amount = temp_i;
	cur = c;
}

double Money::get_amount_decimal() {
	return double(amount) / 100;
}

void read_value(currency & c, double& i) {
	string cur;
	char l;
	double amount;

	while (true) {
		cin >> l;
		if (isalpha(l)) {
			cur += l;
		}
		else {
			if (cur == "USD" || cur == "EUR" || cur == "GBP") {
				if (cur == "USD") {
					c = currency::USD;
				}
				else if (cur == "EUR") {
					c = currency::EUR;
				}
				else if (cur == "GBP") {
					c = currency::GBP;
				}
			}
			else {
				cout << "Invalid currency" << cur << endl;
				break;
			}

			cin.putback(l);
			cin >> amount;

			i = amount;
			break;
		}
	}
}

double EURtoUSD(double d) {
	return d * 1.12;
}

double GBPtoUSD(double d) {
	return d * 1.26;
}

double USDtoEUR(double d) {
	return d * 0.89;
}

double GBPtoEUR(double d) {
	return d * 1.13;
}

double USDtoGBP(double d) {
	return d * 0.78;
}

double EURtoGBP(double d) {
	return d * 0.88;
}

Money operator+(Money & m1, Money & m2) {
	
	switch (m1.cur) {
	case USD:{
		switch (m2.cur) {
		case USD: {return Money(USD, m1.get_amount_decimal() + m2.get_amount_decimal()); }
		case EUR: {return Money(USD, m1.get_amount_decimal() + EURtoUSD(m2.get_amount_decimal())); }
		case GBP: {return Money(USD, m1.get_amount_decimal() + GBPtoUSD(m2.get_amount_decimal())); }
		}
	}
	case EUR:{
		switch (m2.cur) {
		case USD: {return Money(m1.get_amount_decimal() + USDtoEUR(m2.get_amount_decimal())); }
		case EUR: {return Money(m1.get_amount_decimal() + m2.get_amount_decimal()); }
		case GBP: {return Money(m1.get_amount_decimal() + GBPtoEUR(m2.get_amount_decimal())); }
		}
	}
	case GBP:{
		switch (m2.cur) {
		case USD: {return Money(GBP, m1.get_amount_decimal() + USDtoGBP(m2.get_amount_decimal())); }
		case EUR: {return Money(GBP, m1.get_amount_decimal() + EURtoGBP(m2.get_amount_decimal())); }
		case GBP: {return Money(GBP, m1.get_amount_decimal() + m2.get_amount_decimal()); }
		}
	}
	}
	
}


void calculate() {

	double input1;
	currency cur1;
	double input2;
	currency cur2;

	cout << "Enter first set of money as float: " << endl;
	cout << "Supported currencies: EUR, GBP, USD," << endl;
	cout << "Format example: USD 12.235" << endl;
	read_value(cur1, input1);
	Money money1(cur1, input1);
	money1.print();

	cout << "Enter second set of money as float: " << endl;
	cout << "Supported currencies: EUR, GBP, USD," << endl;
	cout << "Format example: USD 12.235" << endl;

	read_value(cur2, input2);
	Money money2(cur2, input2);
	money2.print();

	Money money3 = money1 + money2;
	cout << "money1 + money2 = ";
	money3.print();
}


int main()
try
{
	calculate();
	keep_window_open();
}

catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}
Output:
Enter first set of money as float:
Supported currencies: EUR, GBP, USD,
Format example: USD 12.235
GBP 23.456
GBP23.46
Enter second set of money as float:
Supported currencies: EUR, GBP, USD,
Format example: USD 12.235
USD 50.235
USD50.24
money1 + money2 = GBP62.65
Please enter a character to exit

money class 1.0

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 14
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 14

#include "std_lib_facilities.h"

class Money {
private:
	long int amount;
public:
	//constructors
	Money(double);
	
	//non-modifying operations
	long int get_amount() { return amount; }
	double get_amount_decimal();
	void print() { cout << get_amount_decimal() << endl; }

	//modifying operations
};

Money::Money(double a) {
	double temp_d0 = a;
	temp_d0 *= 100;
	int temp_i = (int)temp_d0;
	double difference = temp_d0 - temp_i;

	if (difference >= 0.5) {
		temp_i++;
	}

	amount = temp_i;
}

double Money::get_amount_decimal() {
	return double(amount) / 100;
}

void read_value(string& c, double& i) {
	string check;
	double input;

	if (cin >> input) {
		i = input;
	}
	else {
		cin.clear();
		cin >> check;
		c = check;
		if (check != "x") {
			cout << "Invalid input: " << check << endl;
		}
	}
}

void calculate() {
	while (true) {
		string check;
		double input;
		cout << "Enter dollar amount as float: " << endl;
		read_value(check, input);
		if (check == "x") {
			break;
		}
		else {
			Money dollar(input);
			dollar.print();
		}
	}
}

int main()
try
{
	calculate();
	keep_window_open();
}

catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}
Output:
Enter dollar amount as float:
34.5346
34.53
Enter dollar amount as float:
34.566
34.57
Enter dollar amount as float:

rational number class

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 13
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 13

#include "std_lib_facilities.h"

//find greatest common denominator
int find_gcd(int a, int b)
{
	while (b != 0) {
		int temp = b;
		b = a % b;
		a = temp;
		cout << "a = " << a << endl;
		cout << "b = " << b << endl;
	}
	cout << "final a = " << a << endl;
	return a;
}

class Rational {
private:
	int numerator;
	int denominator;
	double solution;

public:
	Rational();
	Rational(int, int);

	int get_numerator() { return numerator; }
	int get_denominator()  { return denominator; }
	double get_solution() { return solution; }

	void print_solution() { cout << solution << endl; }

	void normalise();
	void convert_to_double();
	
	void operator=(Rational r1);
};

Rational::Rational() {
	numerator = 1;
	denominator = 1;
}

Rational::Rational(int a, int b) {
	numerator = a;
	denominator = b;
}

void Rational::normalise() {
	if (denominator == 0) error("denominator is zero");
	if (denominator < 0) { denominator = -denominator; numerator = -numerator; }
	int n = find_gcd(numerator, denominator);
	if (n > 1) { numerator /= n; denominator /= n; }
}

void Rational::convert_to_double() {
	solution = double(numerator) / double(denominator);
}

void Rational::operator=(Rational r1) {
	numerator = r1.get_numerator();
	denominator = r1.get_denominator();
}

Rational operator+(Rational r1, Rational r2) {
	int a = r1.get_numerator() + r2.get_numerator();
	int b = r1.get_denominator() + r2.get_denominator();
	Rational r(a,b);
	return r;
}

Rational operator-(Rational r1, Rational r2) {
	int a = r1.get_numerator() - r2.get_numerator();
	int b = r1.get_denominator() - r2.get_denominator();
	Rational r(a, b);
	return r;
}

Rational operator*(Rational r1, Rational r2) {
	int a = r1.get_numerator() * r2.get_numerator();
	int b = r1.get_denominator() * r2.get_denominator();
	Rational r(a, b);
	return r;
}

Rational operator/(Rational r1, Rational r2) {
	int a = r1.get_numerator() / r2.get_numerator();
	int b = r1.get_denominator() / r2.get_denominator();
	Rational r(a, b);
	return r;
}

bool operator==(Rational r1, Rational r2) {
	bool a = r1.get_numerator() == r2.get_numerator();
	bool b = r1.get_denominator() == r2.get_denominator();
	if (a && b) {
		return true;
	}
	else {
		return false;
	}
}

bool operator!=(Rational r1, Rational r2) {
	bool a = r1.get_numerator() != r2.get_numerator();
	bool b = r1.get_denominator() != r2.get_denominator();
	if (a && b) {
		return true;
	}
	else {
		return false;
	}
}

int main()
try
{
	Rational myRational(30, 23);
	Rational myRational1(21,4);

	myRational = myRational + myRational1;
	myRational.convert_to_double();
	myRational.print_solution();

	myRational = myRational - myRational1;
	myRational.convert_to_double();
	myRational.print_solution();

	myRational = myRational * myRational1;
	myRational.convert_to_double();
	myRational.print_solution();

	myRational = myRational / myRational1;
	myRational.convert_to_double();
	myRational.print_solution();

	myRational = myRational1;
	myRational.convert_to_double();
	myRational.print_solution();


	if (myRational1 == myRational) {
		cout << "rational numbers are equal" << endl;
	}

	if (myRational1 != myRational) {
		cout << "rational numbers are not equal" << endl;
	}

	keep_window_open();
}
catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}
Output:
1.88889
1.30435
6.84783
1.30435
5.25
rational numbers are equal
Please enter a character to exit

book class 1.5 [adding leapyear …]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 10 + 11 + 12
Using std_lib_facilities.h by Bjarne Stroustrup.
Using Chrono.h and Chrono.cpp by Bjarne Stroustrup,
including the Chrono.h header file and the Chrono.cpp source file. Chrono is an extensive date class used in this exercise.

Exercise 10, 11 and 12 unfortunately were already by Bjarne Stroustrup himself, since the changes to be made are already implemented in the Chrono.h and Chrono.cpp file I linked above. I hope I’m not mistaken on this and I did not just cheekily skip 3 exercises of the book. (Tell me if I did!)

book class 1.4 [adding library class]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 9
Using std_lib_facilities.h by Bjarne Stroustrup.
Using Chrono.h and Chrono.cpp by Bjarne Stroustrup,
including the Chrono.h header file and the Chrono.cpp source file. Chrono is an extensive date class used in this exercise.

My project includes the following files:
Chrono.h date class header file
Chrono.cpp date class source file
p340_9_book_main.cpp my main cpp file
p340_9_my_book_class.h my book class header file
p340_9_book_source.cpp my book class header file’s source file

p340_9_book_main.cpp my main cpp file

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 9

#include "p340_9_my_book_class.h"
using namespace Chrono;

Library my_Library;

void add_books() {
	Book my_Book(ISBN(), "book1", "author1", Date(2000, Date::jul, 5), Genre::biography, false);
	my_Library.add_book(my_Book);
}

int main()
try
{
	add_books();
	Patron examplePatron("Phil", 100);
	cout << examplePatron;
	keep_window_open();
}
catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}

/*if (year is not divisible by 4) then (it is a common year)
else if (year is not divisible by 100) then (it is a leap year)
else if (year is not divisible by 400) then (it is a common year)
else (it is a leap year)

common year = 365 days
leap year = 366 days
*/

p340_9_my_book_class.h header file

#include "std_lib_facilities.h"
#include "Chrono.h"
using namespace Chrono;

//BOOK CLASS------
struct ISBN {
	int n0, n1, n2;
	char x;
	ISBN(int n0, int n1, int n2, char x);
	ISBN();
};

// exercise 7 genre enumerator
enum Genre {
	fiction = 0,
	nonfiction,
	periodical,
	biography,
	children
};

class Book {
private:
	ISBN isbn;
	string title;
	string author;
	Date copyright_date;
	Genre genre;
	bool checked_out;

public:
	Book(ISBN _isbn, string _title, string _author, Date _copyright_date, Genre _genrebook, bool _checked_out);
	Book();
	ISBN isbnf() { return isbn; }
	string titlef() { return title; }
	string authorf() { return author; }
	Date copyright_datef() { return copyright_date; }
	Genre genref() { return genre; }
	bool checked_outf() { return checked_out; }
	void book_out();
	void book_in();
};

//exercise 6 operator overloading
ostream& operator << (ostream&, ISBN&);
ostream& operator << (ostream&, const Genre&);
ostream& operator << (ostream&, Book&);
bool operator ==(ISBN&, ISBN&);
bool operator !=(ISBN&, ISBN&);

//endBOOK CLASS------

//PATRON CLASS------
class Patron {
private:
	string patron_name;
	int patron_num;
	bool fee_owed;
	double fee_amount;
public:
	Patron(string _patron_name, int _patron_num);
	Patron();

	string patron_namef() { return patron_name; }
	int patron_numf() { return patron_num; }
	bool fee_owedf() { return fee_owed; }
	double fee_amountf() { return fee_amount; }

	void add_fee(double _fee);
};

ostream& operator << (ostream&, Patron&);

//endPATRON CLASS------

//LIBRARY CLASS------

struct Transaction {
	Book book;
	Patron patron;
	Date date;

	Transaction(Book _book, Patron _patron, Date _date) {
		book = _book;
		patron = _patron;
		date = _date;
	}
};

class Library {
private:
	vector<Book> books;
	vector<Patron> patrons;
	vector<Transaction> transactions;
public:

	vector<Patron> patronsf() { return patrons; }
	vector<Book> booksf() { return books; }

	void add_book(Book);
	void add_patron(Patron);
	void add_transaction(Book, Patron, Date);
	void fee_check();
};

bool operator ==(Book&, Book&);

//endLIBRARY CLASS------

p340_9_book_source.cpp my book class header file’s source file

#include "p340_9_my_book_class.h"


//BOOK CLASS_HELPER FUNCTIONS------

ISBN::ISBN(int _n0, int _n1, int _n2, char _x) {
	n0 = _n0;
	n1 = _n1;
	n2 = _n2;
	x = _x;
}

ISBN::ISBN() {
	n0 = 0;
	n1 = 0;
	n2 = 0;
	x = '0';
}

Book::Book(ISBN _isbn, string _title, string _author, Date _copyright_date, Genre _genrebook, bool _checked_out) {
	cout << "--- Creating book ---\n";
	isbn = _isbn;
	title = _title;
	author = _author;
	copyright_date = _copyright_date;
	genre = _genrebook;
	checked_out = _checked_out;
};

Book::Book() {
	cout << "--- Creating book ---\n";
	isbn = ISBN(0, 0, 0, 0);
	title = "";
	author = "";
	copyright_date = Date();
	genre = Genre();
	checked_out = false;
}

void Book::book_out() {
	checked_out = true;
};

void Book::book_in() {
	checked_out = false;
};

ostream& operator << (ostream& os, ISBN& _isbn) {
	os << _isbn.n0 << _isbn.n1 << _isbn.n2 << _isbn.x;
	return os;
}

ostream& operator << (ostream& os, const Genre& _genre) {
	switch (_genre) {
	case Genre::biography:
		os << "biography";
		return os;
	case Genre::children:
		os << "children";
		return os;
	case Genre::fiction:
		os << "fiction";
		return os;
	case Genre::nonfiction:
		os << "nonfiction";
		return os;
	case Genre::periodical:
		os << "periodical";
		return os;
	}
}

ostream& operator << (ostream& os, Book& _book) {
	os << "ISBN: " << _book.isbnf() << "\n"
		<< "Title: " << _book.titlef() << "\n"
		<< "Author: " << _book.authorf() << "\n"
		<< "Copyright Date: " << _book.copyright_datef() << "\n"
		<< "Genre: " << _book.genref() << "\n"
		<< "Checked out: " << boolalpha << _book.checked_outf() << "\n";
	return os;
}

bool operator ==(ISBN& book1, ISBN& book2) {
	if (book1 == book2) {
		return true;
	}
	else {
		return false;
	}
}

bool operator !=(ISBN& book1, ISBN& book2) {
	if (book1 != book2) {
		return true;
	}
	else {
		return false;
	}
}

//endBOOK CLASS_HELPER FUNCTIONS------



//PATRON CLASS_HELPER FUNCTIONS------

Patron::Patron(string _patron_name, int _patron_num) {
	cout << "--- Creating Patron ---\n";
	patron_name = _patron_name;
	patron_num = _patron_num;
	fee_owed = false;
	fee_amount = 0;
}

Patron::Patron() {
	cout << "--- Creating Patron ---\n";
	patron_name = "";
	patron_num = 0000;
	fee_owed = false;
	fee_amount = 0;
}

void Patron::add_fee(double _fee) {
	fee_amount += _fee;
	if (fee_amount != 0) {
		fee_owed = true;
	}
	else {
		fee_owed = false;
	}
}

ostream& operator << (ostream& os, Patron& _patron) {
	os << "Patron Name: " << _patron.patron_namef() << "\n"
		<< "Patron Number: " << _patron.patron_numf() << "\n"
		<< "Fee owed: " << boolalpha << _patron.fee_owedf() << "\n"
		<< "Fee owed: " << _patron.fee_amountf() << "\n";
	return os;
}

//endPATRON CLASS_HELPER FUNCTIONS------



//LIBRARY CLASS_HELPER FUNCTIONS------

bool operator ==(Book& _book1, Book& _book2) {
	if (_book1.isbnf() == _book2.isbnf()
		&& _book1.titlef() == _book2.titlef()
		&& _book1.authorf() == _book2.authorf()) {
		return true;
	}
	else {
		return false;
	}
}

bool operator ==(Patron& _patron1, Patron& _patron2) {
	if (_patron1.patron_namef() == _patron2.patron_namef()
		&& _patron1.patron_numf() == _patron2.patron_numf()) {
		return true;
	}
	else {
		return false;
	}
}

void Library::add_book(Book _book) {
	if (books.size() == 0) {
		books.push_back(_book);
	}
	else {
		int counter = 0;
		for (int i = 0; i < books.size(); i++) {
			if (books[i] == _book) {
				cout << "Book already exists in Library\n";
				counter++;
			}
		}
		if (counter == 0) {
			books.push_back(_book);
		}
	}
}

void Library::add_patron(Patron _patron) {
	if (patrons.size() == 0) {
		patrons.push_back(_patron);
	}
	else {
		int counter = 0;
		for (int i = 0; i < patrons.size(); i++) {
			if (patrons[i] == _patron) {
				cout << "Patron already exists in Library\n";
				counter++;
			}
		}
		if (counter == 0) {
			patrons.push_back(_patron);
		}
	}
}

void Library::add_transaction(Book _book, Patron _patron, Date _date) {
	bool book_ckeck = false;
	bool patron_check = false;

	//book check
	for (int i = 0; i < books.size(); i++) {
		if (books[i] == _book) {
			book_ckeck = true;
		}
	}
	if (!book_ckeck) {
		cout << "Book does not exist in Library\n";
	}

	//patron check
	for (int i = 0; i < patrons.size(); i++) {
		if (patrons[i] == _patron) {
			patron_check = true;
		}
	}
	if (!patron_check) {
		cout << "Patron does not exist in Library\n";
	}

	//adding transaction
	if (!_book.checked_outf() && book_ckeck && patron_check) {
		_book.book_out();
		transactions.push_back(Transaction(_book, _patron, _date));
		cout << "Book checked out!\n";
	}
	else {
		_book.book_in();
		transactions.push_back(Transaction(_book, _patron, _date));
		cout << "Book checked in!\n";
	}
}

void Library::fee_check() {
	for (int i = 0; i < patrons.size(); i++) {
		if (patrons[i].fee_owedf()) {
			cout << patrons[i].patron_namef() << "\n";
			cout << patrons[i].fee_amountf() << "\n";
		}
	}
}

//endLIBRARY CLASS_HELPER FUNCTIONS------
Output:
--- Creating book ---
--- Creating Patron ---
Patron Name: Phil
Patron Number: 100
Fee owed: false
Fee owed: 0
Please enter a character to exit

book class 1.3 [adding patron class]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 8
Using std_lib_facilities.h by Bjarne Stroustrup.
Using Chrono.h and Chrono.cpp by Bjarne Stroustrup,
including the Chrono.h header file and the Chrono.cpp source file. Chrono is an extensive date class used in this exercise.

My project includes the following files:
Chrono.h date class header file
Chrono.cpp date class source file
p340_8_book_main.cpp my main cpp file
p340_8_my_book_class.h my book class header file
p340_8_book_source.cpp my book class header file’s source file

p340_8_book_main.cpp my main cpp file

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 8

#include "p340_8_my_book_class.h"
using namespace Chrono;

void add_books() {
	Book my_Book(ISBN(), "book1", "author1", Date(2000, Date::jul, 5), Genre::biography, false);
}

int main()
try
{
	add_books();
	Patron examplePatron("Phil", 100);
	cout << examplePatron;
	keep_window_open();
}
catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}

p340_8_my_book_class.h header file

#include "std_lib_facilities.h"
#include "Chrono.h"
using namespace Chrono;

//BOOK CLASS------
struct ISBN {
	int n0, n1, n2;
	char x;
	ISBN(int n0, int n1, int n2, char x);
	ISBN();
};

// exercise 7 genre enumerator
enum Genre {
	fiction = 0,
	nonfiction,
	periodical,
	biography,
	children
};

class Book {
private:
	ISBN isbn;
	string title;
	string author;
	Date copyright_date;
	Genre genre;
	bool checked_out;

public:
	Book(ISBN _isbn, string _title, string _author, Date _copyright_date, Genre _genrebook, bool _checked_out);
	Book();
	ISBN isbnf() { return isbn; }
	string titlef() { return title; }
	string authorf() { return author; }
	Date copyright_datef() { return copyright_date; }
	Genre genref() { return genre; }
	bool checked_outf() { return checked_out; }
	void book_out();
	void book_in();
};

//exercise 6 operator overloading
ostream& operator << (ostream&, ISBN&);
ostream& operator << (ostream&, const Genre&);
ostream& operator << (ostream&, Book&);
bool operator ==(ISBN&, ISBN&);
bool operator !=(ISBN&, ISBN&);

//endBOOK CLASS------

//PATRON CLASS------
class Patron {
private:
	string patron_name;
	int patron_num;
	bool fee_owed;
	double fee_amount;
public:
	Patron(string _patron_name, int _patron_num);
	Patron();

	string patron_namef() { return patron_name; }
	int patron_numf() { return patron_num; }
	bool fee_owedf() { return fee_owed; }
	double fee_amountf() { return fee_amount; }

	void add_fee(double _fee);
};

ostream& operator << (ostream&, Patron&);

//endPATRON CLASS------

p340_8_book_source.cpp my book class header file’s source file

#include "p340_8_my_book_class.h"


//BOOK CLASS_HELPER FUNCTIONS------

ISBN::ISBN(int _n0, int _n1, int _n2, char _x) {
	n0 = _n0;
	n1 = _n1;
	n2 = _n2;
	x = _x;
}

ISBN::ISBN() {
	n0 = 0;
	n1 = 0;
	n2 = 0;
	x = '0';
}

Book::Book(ISBN _isbn, string _title, string _author, Date _copyright_date, Genre _genrebook, bool _checked_out) {
	cout << "--- Creating book ---\n";
	isbn = _isbn;
	title = _title;
	author = _author;
	copyright_date = _copyright_date;
	genre = _genrebook;
	checked_out = _checked_out;
};

Book::Book() {
	cout << "--- Creating book ---\n";
	isbn = ISBN(0, 0, 0, 0);
	title = "";
	author = "";
	copyright_date = Date();
	genre = Genre();
	checked_out = false;
}

void Book::book_out() {
	checked_out = true;
};

void Book::book_in() {
	checked_out = false;
};

ostream& operator << (ostream& os, ISBN& _isbn) {
	os << _isbn.n0 << _isbn.n1 << _isbn.n2 << _isbn.x;
	return os;
}

ostream& operator << (ostream& os, const Genre& _genre) {
	switch (_genre) {
	case Genre::biography:
		os << "biography";
		return os;
	case Genre::children:
		os << "children";
		return os;
	case Genre::fiction:
		os << "fiction";
		return os;
	case Genre::nonfiction:
		os << "nonfiction";
		return os;
	case Genre::periodical:
		os << "periodical";
		return os;
	}
}

ostream& operator << (ostream& os, Book& _book) {
	os << "ISBN: " << _book.isbnf() << "\n"
		<< "Title: " << _book.titlef() << "\n"
		<< "Author: " << _book.authorf() << "\n"
		<< "Copyright Date: " << _book.copyright_datef() << "\n"
		<< "Genre: " << _book.genref() << "\n"
		<< "Checked out: " << boolalpha << _book.checked_outf() << "\n";
	return os;
}

bool operator ==(ISBN& book1, ISBN& book2) {
	if (book1 == book2) {
		return true;
	}
	else {
		return false;
	}
}

bool operator !=(ISBN& book1, ISBN& book2) {
	if (book1 != book2) {
		return true;
	}
	else {
		return false;
	}
}

//endBOOK CLASS_HELPER FUNCTIONS------



//PATRON CLASS_HELPER FUNCTIONS------

Patron::Patron(string _patron_name, int _patron_num) {
	cout << "--- Creating Patron ---\n";
	patron_name = _patron_name;
	patron_num = _patron_num;
	fee_owed = false;
	fee_amount = 0;
}

Patron::Patron() {
	cout << "--- Creating Patron ---\n";
	patron_name = "";
	patron_num = 0000;
	fee_owed = false;
	fee_amount = 0;
}

void Patron::add_fee(double _fee) {
	fee_amount += _fee;
	if (fee_amount != 0) {
		fee_owed = true;
	}
	else {
		fee_owed = false;
	}
}

ostream& operator << (ostream& os, Patron& _patron) {
	os << "Patron Name: " << _patron.patron_namef() << "\n"
		<< "Patron Number: " << _patron.patron_numf() << "\n"
		<< "Fee owed: " << boolalpha << _patron.fee_owedf() << "\n"
		<< "Fee owed: " << _patron.fee_amountf() << "\n";
	return os;
}

//endPATRON CLASS_HELPER FUNCTIONS------
Output:
--- Creating book ---
--- Creating Patron ---
Patron Name: Phil
Patron Number: 100
Fee owed: false
Fee owed: 0
Please enter a character to exit

book class 1.2 [genre enumerator]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 7
Using std_lib_facilities.h by Bjarne Stroustrup.
Using Chrono.h and Chrono.cpp by Bjarne Stroustrup,
including the Chrono.h header file and the Chrono.cpp source file. Chrono is an extensive date class used in this exercise.

My project includes the following files:
Chrono.h date class header file
Chrono.cpp date class source file
p340_7_book_main.cpp my main cpp file
p340_7_my_book_class.h my book class header file
p340_7_book_source.cpp my book class header file’s source file

p340_7_book_main.cpp my main cpp file

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 7

#include "p340_7_my_book_class.h"
using namespace Chrono;

int main()
try
{
	Book myBook(ISBN(), "book1", "author1", Date(2000, Date::jul, 5), Genre(0), false);
	cout << myBook;
	keep_window_open();

	keep_window_open();
}
catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}

p340_7_my_book_class.h header file

#include "std_lib_facilities.h"
#include "Chrono.h"
using namespace Chrono;

//BOOK CLASS------
struct ISBN {
	int n0, n1, n2;
	char x;
	ISBN(int n0, int n1, int n2, char x);
	ISBN();
};

// exercise 7 genre enumerator
enum Genre {
	fiction = 0,
	nonfiction,
	periodical,
	biography,
	children
};

class Book {
private:
	ISBN isbn;
	string title;
	string author;
	Date copyright_date;
	Genre genre;
	bool checked_out;

public:
	Book(ISBN _isbn, string _title, string _author, Date _copyright_date, Genre _genrebook, bool _checked_out);
	Book();
	ISBN isbnf() { return isbn; }
	string titlef() { return title; }
	string authorf() { return author; }
	Date copyright_datef() { return copyright_date; }
	Genre genref() { return genre; }
	bool checked_outf() { return checked_out; }
	void book_out();
	void book_in();
};

//exercise 6 operator overloading
ostream& operator << (ostream&, ISBN&);
ostream& operator << (ostream&, const Genre&);
ostream& operator << (ostream&, Book&);
bool operator ==(ISBN&, ISBN&);
bool operator !=(ISBN&, ISBN&);
//endBOOK CLASS------

p340_7_book_source.cpp my book class header file’s source file

#include "p340_7_my_book_class.h"

//BOOK CLASS_HELPER FUNCTIONS------

ISBN::ISBN(int _n0, int _n1, int _n2, char _x) {
	n0 = _n0;
	n1 = _n1;
	n2 = _n2;
	x = _x;
}

ISBN::ISBN() {
	n0 = 0;
	n1 = 0;
	n2 = 0;
	x = '0';
}

Book::Book(ISBN _isbn, string _title, string _author, Date _copyright_date, Genre _genrebook, bool _checked_out) {
	cout << "--- Creating book ---\n";
	isbn = _isbn;
	title = _title;
	author = _author;
	copyright_date = _copyright_date;
	genre = _genrebook;
	checked_out = _checked_out;
};

Book::Book() {
	cout << "--- Creating book ---\n";
	isbn = ISBN(0,0,0,0);
	title = "";
	author = "";
	copyright_date = Date();
	genre = Genre();
	checked_out = false;
}

void Book::book_out() {
	checked_out = true;
};

void Book::book_in() {
	checked_out = false;
};

ostream& operator << (ostream& os, ISBN& _isbn) {
	os << _isbn.n0 << _isbn.n1 << _isbn.n2 << _isbn.x;
	return os;
}

ostream& operator << (ostream& os, const Genre& _genre) {
	switch (_genre){
	case Genre::biography:
		os << "biography";
		return os;
	case Genre::children:
		os << "children";
		return os;
	case Genre::fiction:
		os << "fiction";
		return os;
	case Genre::nonfiction:
		os << "nonfiction";
		return os;
	case Genre::periodical:
		os << "periodical";
		return os;
	}
}

ostream& operator << (ostream& os, Book& _book) {
	os << "ISBN: " << _book.isbnf() << "\n"
		<< "Title: " << _book.titlef() << "\n"
		<< "Author: " << _book.authorf() << "\n"
		<< "Copyright Date: " << _book.copyright_datef() << "\n"
		<< "Genre: " << _book.genref() << "\n"
		<< "Checked out: " << boolalpha << _book.checked_outf() << "\n";
	return os;
}

bool operator ==(ISBN& book1, ISBN& book2) {
	if (book1 == book2) {
		return true;
	}
	else {
		return false;
	}
}

bool operator !=(ISBN& book1, ISBN& book2) {
	if (book1 != book2) {
		return true;
	}
	else {
		return false;
	}
}

//endBOOK CLASS_HELPER FUNCTIONS------
Output:
--- Creating book ---
ISBN: 0000
Title: book1
Author: author1
Copyright Date: (2000,7,5)
Genre: fiction
Checked out: false
Please enter a character to exit

book class 1.1 [adding operators]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 9 Exercise 6
Using std_lib_facilities.h by Bjarne Stroustrup.
Using Chrono.h and Chrono.cpp by Bjarne Stroustrup,
including the Chrono.h header file and the Chrono.cpp source file. Chrono is an extensive date class used in this exercise.

My project includes the following files:
Chrono.h date class header file
Chrono.cpp date class source file
p340_6_book_main.cpp my main cpp file
p340_6_my_book_class.h my book class header file
p340_6_book_source.cpp my book class header file’s source file

p340_6_book_main.cpp my main cpp file

//	Philipp Siedler
//	Bjarne Stroustrup's PPP
//	Chapter 9 Exercise 6

#include "p340_6_my_book_class.h"
using namespace Chrono;

int main()
try
{
	Book myBook(ISBN(), "book1", "author1", Date(2000, Date::jul, 5), false);
	cout << myBook;
	keep_window_open();
}
catch (runtime_error e) {
	cout << e.what() << endl;
	keep_window_open();
}
catch (...) {
	cout << "Exiting" << endl;
	keep_window_open();
}

p340_6_my_book_class.h header file

#include "std_lib_facilities.h"
#include "Chrono.h"
using namespace Chrono;

//BOOK CLASS------
struct ISBN {
	int n0, n1, n2;
	char x;
	ISBN(int n0, int n1, int n2, char x);
	ISBN();
};

class Book {
private:
	ISBN isbn;
	string title;
	string author;
	Date copyright_date;
	bool checked_out;

public:
	Book(ISBN _isbn, string _title, string _author, Date _copyright_date, bool _checked_out);
	Book();
	ISBN isbnf() { return isbn; }
	string titlef() { return title; }
	string authorf() { return author; }
	Date copyright_datef() { return copyright_date; }
	bool checked_outf() { return checked_out; }
	void book_out();
	void book_in();
};

//exercise 6 operator overloading
ostream& operator << (ostream&, ISBN&);
ostream& operator << (ostream&, Book&);
bool operator ==(ISBN&, ISBN&);
bool operator !=(ISBN&, ISBN&);
bool operator ==(Book&, Book&);

//endBOOK CLASS------

p340_6_book_source.cpp my book class header file’s source file

#include "p340_6_my_book_class.h"

ISBN::ISBN(int _n0, int _n1, int _n2, char _x) {
	n0 = _n0;
	n1 = _n1;
	n2 = _n2;
	x = _x;
}

ISBN::ISBN() {
	n0 = 0;
	n1 = 0;
	n2 = 0;
	x = '0';
}

Book::Book(ISBN _isbn, string _title, string _author, Date _copyright_date, bool _checked_out) {

	cout << "Creating book\n";
	isbn = _isbn;
	title = _title;
	author = _author;
	copyright_date = _copyright_date;
	checked_out = _checked_out;
};

void Book::book_out() {
	checked_out = true;
};

void Book::book_in() {
	checked_out = false;
};

ostream& operator << (ostream& os, ISBN& _isbn) {
	os << _isbn.n0 << _isbn.n1 << _isbn.n2 << _isbn.x;
	return os;
}

ostream& operator << (ostream& os, Book& _book) {
	os << "ISBN: " << _book.isbnf() << "\n"
		<< "Title: " << _book.titlef() << "\n"
		<< "Author: " << _book.authorf() << "\n"
		<< "Copyright Date: " << _book.copyright_datef() << "\n"
		<< "Checked out: " << boolalpha << _book.checked_outf() << "\n";
	return os;
}

bool operator ==(ISBN& book1, ISBN& book2) {
	if (book1 == book2) {
		return true;
	}
	else {
		return false;
	}
}

bool operator !=(ISBN& book1, ISBN& book2) {
	if (book1 != book2) {
		return true;
	}
	else {
		return false;
	}
}
Output:
Creating book
ISBN: 0000
Title: book1
Author: author1
Copyright Date: (2000,7,5)
Checked out: false
Please enter a character to exit