In this assignment, you will write a main program and several classes to create and print a small collection of bank accounts. You will also apply deposit and withdrawal transactions to those bank accounts.
Log in to Unix.
Run the setup
script for Assignment 5 by typing:
setup 5
Input for this program consists of two files.
The first file, named accounts
, contains a single bank
object written out in binary format. This object will be read by the read_accounts()
member function of the bank
class (see the member function description below for additional details). Since this is a binary file, you will not be able to read the data in it using the >>
operator. See the notes on the course website covering Binary Input and Output / Object Serialization for a description of the technique you will need to use to read this file. Note that reading an entire bank
object using ifstream::read()
will be very similar to the code in the notes that reads an entire Course
object.
The second file, named transactions.txt
, contains a series of transaction records in ASCII character format, which means that you can use the >>
operator to read the fields of these records. A typical transaction is shown below. The first field on the transaction record is the date of the transaction, followed by an account number, then the transaction type ('D' for deposit or 'W' for withdrawal), and finally a transaction amount.
06/19 1111111111 D 430.00
You will need to declare variables to hold the data read for each of these fields. To read transaction records until end of file is reached, use a loop like the following:
while (trans_file >> date) { // Read remaining data of the transaction record. trans_file >> account_number; trans_file >> type; trans_file >> amount; // Process this transaction. . . . }
where trans_file
is the name of the ifstream
variable opened for the transaction file.
The setup script will create the directory Assign5
under your csci241
directory. It will copy a makefile named makefile
to the assignment directory. Like the makefile for Assignment 4, this makefile has only a single executable target named assign5
. You can build the entire project for Assignment 5 simply by typing the command make
.
Running the command make clean
will remove all of the object and executable files created by the make
command.
You will also receive symbolic links to the two data files named accounts
and transactions.txt
described above under 2. Input.
You will write five files for this assignment:
account.h
This header file will contain the class definition for a class called account
. The account
class represents information about a person's bank account. The header file should include an appropriate set of header guards to prevent it from being included more than once in the same source file.
Data Members
The account
class should have the following private data members:
char
array with room for 10 characters PLUS the null character, i.e. 11 elements total)char
array with room for 20 characters PLUS the null character)double
variable)Note: Make that sure you code your data members in THE EXACT ORDER LISTED ABOVE and with THE EXACT SAME DATA TYPES. If you use float
instead of double
or only make the name array 20 characters long instead of 21, your program will not work correctly.
Member Functions
The account
class definition should contain public prototypes for all of the member functions in the account.cpp
source code file described below.
account.cpp
This source code file will contain the member function definitions for the account
class. The required member functions are described below:
Default constructor
The default constructor should set the account number and customer name data members to the string literal "None"
. The account balance data member should be set to 0.
get_account_number()
This member function has no parameters. It should return the account number.
get_balance()
This member function has no parameters. It should return the current account balance.
process_deposit()
This member function should take a double
deposit amount and add it to the balance for the bank account. It returns nothing.
process_withdrawal()
This member function should take a double
withdrawal amount. If the bank account's balance is less than the withdrawal amount, the member function should just return false
. Otherwise, subtract the withdrawal amount from the balance of the bank account and return true
.
print()
This member function has no parameters and returns nothing. It should print the values of the data members for the account in a format similar to the following:
Account Number: 0003097439 Name: John Smith Balance: $5234.38
bank.h
This header file will contain the class definition for a class called bank
. The bank
class represents information about a collection of bank accounts. The header file should include an appropriate set of header guards to prevent it from being included more than once in the same source file.
Data Members
The bank
class should have the following three private data members:
char
array with room for 30 characters PLUS the null character)account
objectsNote: Once again, make sure that you code your data members in the exact order listed above and with the exact same data types.
Member Functions
The bank
class definition should contain public prototypes for all of the member functions in the bank.cpp
source code file described below.
bank.cpp
This source code file will contain the member function definitions for the bank
class. The required member functions are described below:
Default constructor
The default constructor should set the bank name data member to the string literal "None"
. The number of accounts data member should be set to 0. No initialization is necessary for the array of account
objects, since the account
default constructor will automatically be called for every object in the array.
read_accounts()
This member function takes one parameter, a string that contains the name of a file. This string parameter can be a C++ string or a C string (your choice). The function returns nothing.
This constructor should do the following:
Declare and open an input file stream variable for the file name string passed in as a parameter.
Check to make sure the file was opened successfully. If not, print an error message and exit the program.
Read the database file into your bank
object using the ifstream::read()
member function for binary input.
Close the file stream variable.
Sort the account objects in the array in ascending order by account number using a sorting algorithm of your choice. Note that the account numbers are C strings, which means that you will not be able to compare them using the standard relational operators. The account number is also private data of the account
class, so code in the bank
will need to call get_account_number()
for an account
object rather than accessing the object's account number directly.
Note that the code described above will read data into all of the account
data members. That includes the bank name, the array of 20 account
objects, and the number of array elements filled with valid data. No further initialization of the data members will be needed.
process_transactions()
This member function takes one parameter, a string that contains the name of a file of transaction data. This string parameter can be a C++ string or a C string (your choice). The function returns nothing.
The member function should open the specified transaction file for input. Make sure to test that the file was opened successfully; if it wasn't, print an error message and exit the program.
Before reading any transactions, the function should print a report header and column headers. The function should then read transaction data from the file until end of file is reached.
Once all of the fields for a given transaction have been read, perform a binary search of the accounts array for the account number given in the transaction. If the account number from the transaction record is present in the accounts array, then the transaction may be processed. For a deposit, simply call the process_deposit()
member function for the object that contains the matching account number, passing it the transaction amount. For a withdrawal, call the process_withdrawal()
member function for the object that contains the matching account number, passing it the transaction amount.
For each transaction record processed, print a line in a transaction report with the data from the record and the updated balance for that account. If the transaction account number was not found in the account array or if a charge exceeded the account's credit limit (i.e., if the process_withdrawal()
member function returned false
), print an appropriate error message instead of the account balance. See 5. Output for sample output.
After all transactions have been processed, close the transaction file.
print()
This member function takes no parameters and returns nothing.
This member function should first print a descriptive header line that includes the bank name (e.g., "Account Listing for First National Bank"). It should then loop through the array of account
objects and print each of the elements that contains account data (i.e., element 0 up to but not including element number of accounts), with a blank line between each account.
Here we see some of the power of object-oriented programming. Since the account
class has a print()
member function, you can just call that function for each element of the array to print all the data members of each account
object.
You are welcome to write additional private member functions for the bank
class as you see fit. For example, you may want to put your sorting algorithm code in its own member function and call it from read_accounts()
or place the binary search code in its own member function and call it from process_transactions()
.
main.cpp
This file will contain the program's main()
function. The logic for this function is quite short:
bank
object.bank
object to call the member function read_accounts()
, passing the file name "accounts"
as an argument to the function.print()
member function for the bank
object.process_transactions()
member function for the bank
object. Pass the file name "transactions.txt"
as an argument to the function.print()
member function for the bank
object.The correct output for this assignment is shown below:
Account Listing for First National Bank Account Number: 1132264809 Name: Joanna Madsen Balance: $2805.65 Account Number: 5540853032 Name: Trey Donner Balance: $4850.75 Account Number: 5745648360 Name: Ronald Jones Balance: $1340.53 Account Number: 5745734564 Name: Karin Hunt Balance: $4476.00 Account Number: 6379094723 Name: Blake Reynolds Balance: $2703.62 Account Number: 7307830409 Name: Jon Mitchell Balance: $207.45 Account Number: 7415949234 Name: Susan Garcia Balance: $3738.64 Account Number: 9858542030 Name: Keiko Tanaka Balance: $11343.82 Transaction Report Date Account Type Amount New Balance 08/19 1130034922 D 5500.00 *** Invalid account number *** 08/19 5540853032 W 430.00 4420.75 08/20 7415949234 D 3620.45 7359.09 08/20 9858542030 W 130.00 11213.82 08/20 1132264809 W 3275.23 *** Insufficient funds *** 08/20 6379094723 W 250.00 2453.62 Account Listing for First National Bank Account Number: 1132264809 Name: Joanna Madsen Balance: $2805.65 Account Number: 5540853032 Name: Trey Donner Balance: $4420.75 Account Number: 5745648360 Name: Ronald Jones Balance: $1340.53 Account Number: 5745734564 Name: Karin Hunt Balance: $4476.00 Account Number: 6379094723 Name: Blake Reynolds Balance: $2453.62 Account Number: 7307830409 Name: Jon Mitchell Balance: $207.45 Account Number: 7415949234 Name: Susan Garcia Balance: $7359.09 Account Number: 9858542030 Name: Keiko Tanaka Balance: $11213.82
If you would like a copy of this output to compare against your own program's output using the diff
command, it is available on Unix at the pathname /home/turing/t90kjm1/CS241/Output/Spring2021/Assign5/output5.txt
.
Like Assignment 4, this assignment has a lot of moving parts and you should not try to write all of the code for it and then hope it works. (ProTip: It almost certainly won't.)
Start by writing account.h
and account.cpp
. Consider writing a short main program to create a single account
object and test it by calling the various methods you wrote. The makefile for the assignment assumes that both the account
and bank
classes exist, but you can still build your test program without having written the bank
class by using a command like this:
g++ -Wall -Werror -std=c++11 -o test test.cpp account.cpp
(The above command assumes that your main()
function to test the account
class is in the file test.cpp
.)
The bank
class depends on the account
class, so if your account
class is wrong, the bank
class is guaranteed to be wrong as well. That means there's really no point in trying to code the bank
class until your account
class is right (i.e., compiles without warnings or errors and produces the correct results when its member functions are called).
Once your account
class seems like it works, then you can start working on the bank
class. Start by writing the constructor, the read_accounts()
member function (without the sort code), and the print()
member function. Don't worry about printing the header or getting the output in sorted order by account number, just make sure that you are reading the account data correctly and can print it out.
Next, write code to sort the account objects by account number. Once again, make sure that the sort is working before you move to the next step (binary search won't work on an unsorted array).
The last part of the assignment that you should write is the process_transactions()
member function. Initially, just make sure that you are able to read all the fields of each transaction record. Then add the binary search code and check to make sure that the search works (finds account numbers that are in the array and fails appropriately for account numbers that are not). Next, add the code to process deposits and withdrawals. Check that your account balances are being updated correctly. Finally, write the code to print the transaction report and make sure that your output is formatted in a way that matches the sample output.