1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
/******************************************************
* This program prompts the user for a sequence of bank
* transactions and then prints a bank statement detailing
* the list of deposits, withdrawals, the daily balance for
* each day. Finally, the total interest earned on the account
* is displayed.
******************************************************/
#include <iostream>
#include <list>
#include <string>
#include <cstdlib>
#include <iomanip>
#include <algorithm>
#include "Transaction.h"
#include "TransactionType.h"
#define MONTHLY_INTEREST 0.005
using namespace std;
Transaction promptTransaction();
float promptFloat(string);
bool canParseAsFloat(string);
void showStatement(list<Transaction>);
bool compareByDay(Transaction, Transaction);
int main()
{
//Create a list to store transactions
list<Transaction> transactions;
//Insert initial transaction
transactions.push_back(Transaction(1, 1143.24, string("initial balance"), DEPOSIT));
//Prompt user for transactions
while(true)
{
cout << "Enter a transaction (Y/N): ";
string user;
getline(cin, user);
if(user == "Y" || user == "y")
{
transactions.push_back(promptTransaction());
cout << endl;
}
else if(user == "N" || user == "n")
break;
else
cout << "Invalid command." << endl;
}
//Print bank statement
showStatement(transactions);
}
/**
* Prompt the user for the transaction details,
* create the transaction, and return it.
*/
Transaction promptTransaction()
{
//Prompt transaction day
int day = (int)promptFloat(string("Enter transaction day (e.g. 1): "));
//Prompt transaction type
string type;
bool isWithdrawal = false;
while(true)
{
cout << "Enter 'W' for a withdrawal or 'D' a deposit: ";
getline(cin, type);
if(type == "W" || type == "w")
{
isWithdrawal = true;
break;
}
else if(type == "D" || type == "d")
break;
else
cout << "Invalid type." << endl;
}
//Prompt transaction amount
float amount = promptFloat(string("Enter transaction amount (e.g. 123.99): "));
//Prompt transaction description
cout << "Enter transaction description: ";
string description;
getline(cin, description);
//Create transaction
if(isWithdrawal)
return Transaction(day, amount, description, WITHDRAWAL);
else
return Transaction(day, amount, description, DEPOSIT);
}
/**
* Prompt the user for a floating-point value with the given
* message. If an invalid value is given, the user is re-prompted.
*/
float promptFloat(string msg)
{
while(true)
{
cout << msg;
string val;
getline(cin, val);
if(isalnum(val[0]) && canParseAsFloat(val))
return atof(val.c_str());
else
cout << "Invalid value." << endl;
}
}
/**
* Check whether the given value can be parsed as a floating-point
* number.
*/
bool canParseAsFloat(string val)
{
bool foundDot = false;
for(int i = 0; i < val.size(); i++)
{
if(val[i] == '.')
{
//Can't have two dots
if(foundDot)
return false;
else
foundDot = true;
}
//Each character must be a digit
else if(val[i] < '0' || val[i] > '9')
return false;
}
return true;
}
/**
* Display a formatted table of all the transactions, the daily
* balances, and the interest earned.
*/
void showStatement(list<Transaction> transactions)
{
//Show heading
cout << "\nGenerating statement..." << endl;
//Show transaction table
cout << "\n" << left << setw(5) << "Day" << left << setw(15) << "Amount ($)"
<< left << setw(20) << "Description" << left << setw(15) << "Type"
<< left << setw(15) << "Balance ($)" << endl;
cout << "--------------------------------";
cout << "--------------------------------" << endl;
cout << endl;
//Sort transactions by day
transactions.sort(compareByDay);
//Show transactions and compute daily balance
list<Transaction>::iterator it = transactions.begin();
float balance = 0;
float minBalance = transactions.front().getAmount();
float totalBalance = 0;
float totalInterest = 0;
int month;
int monthOfLastTransaction;
for(; it != transactions.end(); it++)
{
Transaction t = *it;
//Display transaction details
cout << left << setw(5) << t.getDay();
cout << left << setw(15)<< fixed << setprecision(2) << t.getAmount();
cout << left << setw(20) << t.getDescription();
//If this transaction is in a new month
//compute the interest on the current balance
month = (t.getDay()-1)/30;
monthOfLastTransaction = month;
if(month != monthOfLastTransaction)
totalInterest += balance * MONTHLY_INTEREST;
//Display transaction type and update balance
TransactionType type = t.getType();
cout << left << setw(15);
if(type == WITHDRAWAL)
{
balance -= t.getAmount();
cout << "Withdrawal";
}
else
{
balance += t.getAmount();
cout << "Deposit";
}
cout << left << setw(15) << fixed << setprecision(2) << balance << endl;
//Set minimum balance
if(balance < minBalance)
minBalance = balance;
//Set total balance
totalBalance += balance;
}
cout << endl;
//Show minimum balance, average balance, and interest
cout << "Minimum daily balance: $" << fixed << setprecision(2) << minBalance << endl;
cout << "Average daily balance: $" << fixed << setprecision(2) << (totalBalance/transactions.size()) << endl;
cout << "Total interest: $" << fixed << setprecision(2) << totalInterest << endl;
system("PAUSE");
}
/**
* Compare the two transactions by day and return whether the first
* transaction's day is less than the second.
*/
bool compareByDay(Transaction first, Transaction second)
{
return first.getDay() < second.getDay();
}
|