Example Files:
AshikagaAcc.dat
AshikagaAccOrig.dat
EvalData.h
UtilityCls.h
/* Customer Accounts - This program uses a structure to store the following
data about a customer account:
* Name
* Address
* City, State and ZIP
* Telephone Number
* Account Balance
* Date of Last Payment
The structure is used to store customer account records. The program has
a menu that lets the user perform the following operations:
* Enter new records into the file.
* Search for a particular customer's record and display it.
* Search for a particular customer's record and delete it.
* Search for a particular customer's record and change it.
* Display the contents of the entire file
Input Validation: When the data for a new account is entered, it is made
sure that data for all the fields has been entered. No negative account
balances are allowed. */
#include "UtilityCls.h"
#include "EvalDate.h"
const int NAME_SIZE = 20;
const int ADDRESS_SIZE = 20;
const int NUM_SIZE = 12;
const int DATE_SIZE = 11;
struct AccountData
{
char accNumber[NUM_SIZE];
char name[NAME_SIZE];
char address[ADDRESS_SIZE];
char city[ADDRESS_SIZE];
char state[ADDRESS_SIZE];
char zipCode[NUM_SIZE];
char telephoneNumber[NUM_SIZE];
double accountBalance;
char dateLastPayment[DATE_SIZE];
/* Inventory Destructor */
~AccountData()
{
}
};
struct Date
{
int addDay; /* Holds day [1-31] */
int addMonth; /* Holds month [1-12] */
int addYear; /* Holds year */
Date()
{
addDay = 0;
addMonth = 0;
addYear = 0;
}
~Date()
{
}
};
enum class MenuItems
{
ADD_RECORD = 'A', DISPLAY_RECORD = 'D', DISPLAY_ALL = 'C', EDIT_RECORD = 'E',
DELETE_RECORD = 'R', QUIT = 'Q'
};
enum class Choice
{
YES = 'Y', NO = 'N'
};
void menu(AccountData &, const string);
char menuItems(const char, const char, const char,
const char, const char, const char);
string getFileName();
void processRecord(AccountData &, const char, const char, const string);
void getAccountData(AccountData &);
int writeRecord(AccountData &, const string);
void getDate(AccountData &);
string dateToString(const int, const int, const int);
int readRecord(AccountData &, const string);
int editRecord(AccountData &, const char, const char, const string);
int deleteRecord(AccountData &, const char, const char, const string);
void displayRecord(AccountData &);
int displayAll(AccountData &, const string);
int removeRec(AccountData &, fstream &, const string, const string, int);
char getChoice(const char, const char);
int main()
{
AccountData accounts;
string fileName = "";
cout << "\nASHIKAGA BANK - ACCOUNT MANAGER\n\n";
fileName = getFileName();
clearScreen();
menu(accounts, fileName);
pauseSystem();
return 0;
}
/* **********************************************************
Definition: menuItems
This function presents a menu-screen to the user from
which he or she can select one of the available options.
********************************************************** */
char menuItems(const char addRec, const char dispRec, const char dispAll,
const char editRec, const char delRec, const char quit)
{
char menuItem = ' ';
cout << "\n\tASHIKAGA BANK - ACCOUNT MANAGER\n\n";
cout << "\t[A] - [ ADD ] CUSTOMER ACCOUNT RECORD\n"
<< "\t[D] - [ DISPLAY ] CUSTOMER ACCOUNT RECORD\n"
<< "\t[C] - [ DISPLAY ALL ] CUSTOMER ACCOUNT RECORDS\n"
<< "\t[E] - [ EDIT ] CUSTOMER ACCOUNT RECORD\n"
<< "\t[R] - [ REMOVE ] CUSTOMER ACCOUNT RECORD\n"
<< "\t[Q] - [ QUIT ]\n\n";
cout << "\tSELECT MENU ITEM: ";
cin >> menuItem;
menuItem = toupper(menuItem);
while (menuItem < addRec && menuItem > quit)
{
cout << "\n\tMenu item " << menuItem << " does not exist.\n\n"
<< "\tYour selection: ";
cin >> menuItem;
}
return menuItem;
}
/* **********************************************************
Definition: menu
This function accepts a structure variable passed to it by
reference as its argument. It provides a menu structure
that allows the user to select from the following items:
* Add a record
* Display a single customer account record
* Display all customer account records
* Edit a customer record
* Delete a customer record
* Quit
********************************************************** */
void menu(AccountData &accounts, const string fileName)
{
const char addRec = static_cast<char>(MenuItems::ADD_RECORD);
const char dispRec = static_cast<char>(MenuItems::DISPLAY_RECORD);
const char dispAll = static_cast<char>(MenuItems::DISPLAY_ALL);
const char editRec = static_cast<char>(MenuItems::EDIT_RECORD);
const char delRec = static_cast<int>(MenuItems::DELETE_RECORD);
const char quit = static_cast<int>(MenuItems::QUIT);
const char positive = static_cast<char>(Choice::YES);
const char negative = static_cast<char>(Choice::NO);
int selection = 0;
do
{
clearScreen();
selection = menuItems(addRec, dispRec, dispAll, editRec, delRec, quit);
switch (selection)
{
case addRec:
{
clearScreen();
cout << "\n\tASHIKAGA BANK - ADD CUSTOMER ACCOUNT RECORD\n\n";
processRecord(accounts, positive, negative, fileName);
} break;
case dispRec:
{
clearScreen();
cout << "\n\tASHIKAGA BANK - DISPLAY SINGLE CUSTOMER ACCOUNT RECORD\n\n";
readRecord(accounts, fileName);
cin.ignore();
} break;
case dispAll:
{
clearScreen();
cout << "\n\tASHIKAGA BANK - DISPLAY ALL CUSTOMER ACCOUNT RECORDS\n\n";
displayAll(accounts, fileName);
pauseSystem();
} break;
case editRec:
{
clearScreen();
cout << "\n\tASHIKAGA BANK - EDIT CUSTOMER ACCOUNT RECORD\n\n";
editRecord(accounts, positive, negative, fileName);
} break;
case delRec:
{
clearScreen();
cout << "\n\tASHIKAGA BANK - DELETE CUSTOMER ACCOUNT RECORD\n\n";
deleteRecord(accounts, positive, negative, fileName);
} break;
case quit:
{
cout << "\n\tASHIKAGA BANK - CUSTOMER ACCOUNT SYSTEM LOGOUT\n\t"
<< "Remember Policy: Customer First!";
} break;
}
} while (selection != quit);
}
/* **********************************************************
The user is asked for a filename, which is returned from
this function.
********************************************************** */
string getFileName()
{
string fileName = "";
cout << "\nEnter the name of the file to store and retrieve\n"
<< "customer account data: ";
cin >> fileName;
return fileName;
}
/* **********************************************************
Definition: getAccountData
This function accepts a struct variable passed to it by
reference as its argument. The user is asked to enter data
for a customer.
********************************************************** */
void getAccountData(AccountData &accHolder)
{
cout << "\nEnter the following customer account data\n\n";
cout << "Account Number [123-456-789]: ";
cin.ignore();
cin.getline(accHolder.accNumber, NUM_SIZE);
while (strlen(accHolder.accNumber) == ' ' ||
strlen(accHolder.accNumber) < NUM_SIZE-2)
{
cout << "Account Number [123-456-789]: ";
cin.ignore();
cin.getline(accHolder.accNumber, NUM_SIZE);
}
cout << "Customer Name: ";
cin.getline(accHolder.name, NAME_SIZE);
while (strlen(accHolder.name) == '\0')
{
cout << "Customer Name: ";
cin.getline(accHolder.name, NAME_SIZE);
}
cout << "Address: ";
cin.getline(accHolder.address, ADDRESS_SIZE);
while (strlen(accHolder.address) == '\0')
{
cout << "Address: ";
cin.getline(accHolder.address, ADDRESS_SIZE);
}
cout << "City: ";
cin.getline(accHolder.city, ADDRESS_SIZE);
while (strlen(accHolder.city) == '\0')
{
cout << "City: ";
cin.getline(accHolder.city, ADDRESS_SIZE);
}
cout << "State: ";
cin.getline(accHolder.state, ADDRESS_SIZE);
while (strlen(accHolder.state) == '\0')
{
cout << "State: ";
cin.getline(accHolder.state, ADDRESS_SIZE);
}
cout << "Zip-Code: ";
cin.getline(accHolder.zipCode, ADDRESS_SIZE);
while (strlen(accHolder.zipCode) == '\0')
{
cout << "Zip-Code: ";
cin.getline(accHolder.zipCode, NUM_SIZE);
}
cout << "Telephone # ";
cin.getline(accHolder.telephoneNumber, NUM_SIZE);
while (strlen(accHolder.telephoneNumber) == '\0')
{
cout << "Telephone # ";
cin.getline(accHolder.telephoneNumber, NUM_SIZE);
}
cout << "Account Balance: JPY ";
cin >> accHolder.accountBalance;
while (accHolder.accountBalance <= 0)
{
cout << "Account Balance: JPY ";
cin >> accHolder.accountBalance;
}
getDate(accHolder);
}
/* **********************************************************
Definition: getDate
This function accepts a structure variable passed to it by
reference as its argument. It asks and evaluates the date
entered. This information is stored in a member variable
of the Inventory structure.
********************************************************** */
void getDate(AccountData &accHolder)
{
Date addDate;
cin.ignore();
cout << "\nDate added:\n";
cout << "Day: ";
cin >> addDate.addDay;
cout << "Month: ";
cin >> addDate.addMonth;
cout << "Year: ";
cin >> addDate.addYear;
while (validateDate(addDate.addDay, addDate.addMonth, addDate.addYear) == false)
{
cout << "\nInvalid date detected.";
cin.clear();
cout << "\nDate added:\n";
cout << "Day: ";
cin >> addDate.addDay;
cout << "Month: ";
cin >> addDate.addMonth;
cout << "Year: ";
cin >> addDate.addYear;
}
string vDate = dateToString(addDate.addDay, addDate.addMonth,
addDate.addYear);
strcpy_s(accHolder.dateLastPayment, DATE_SIZE, vDate.c_str());
}
/* **********************************************************
Definition: dateToString
This function accepts three integer values as arguments.
A stringstream object is used to store the date in a
specific format, which is returned from the function.
********************************************************** */
string dateToString(const int dd, const int mm, const int yy)
{
stringstream dateStream;
if (dd < 10 && mm < 10)
{
dateStream << "0" << dd << "/0" << mm << "/" << yy;
}
else if (dd >= 10 && mm < 10)
{
dateStream << dd << "/0" << mm << "/" << yy;
}
else
{
dateStream << dd << "/" << mm << "/" << yy;
}
return dateStream.str();
}
/* **********************************************************
Definition: processRecord
This function accepts a structure variable passed to it by
reference and a filename as its arguments. It calls two
functions:
* getItemInfo()
* writeRecord()
As long as the user decides that he or she wishes to add
new customer account records, these function are executed.
If his or her answer is 'N', the function will exit to the
main menu.
********************************************************** */
void processRecord(AccountData &accHolder, const char positive,
const char negative, const string fileName)
{
char choice = ' ';
do
{
getAccountData(accHolder);
writeRecord(accHolder, fileName);
cout << "\nDo you wish to add another customer record? \n";
cin.ignore();
cin.get(choice);
cout << "\n";
choice = toupper(choice);
while (toupper(choice) != positive && toupper(choice) != negative)
{
cout << "\nDo you wish to add another customer record? ";
cin.ignore();
cin.get(choice);
cout << "\n";
}
} while (choice != negative);
}
/* **********************************************************
Definition: writeRecord
This function accepts a structure variable passed to it
by reference and a filename as its arguments. It tries to
open a file in binary write mode. Upon success, data is
written in append mode to the file. If an error occurs, a
message is displayed and the function exits to the menu.
********************************************************** */
int writeRecord(AccountData &accHolder, const string fileName)
{
fstream writeRec(fileName, ios::out | ios::binary | ios::app);
if (!writeRec.fail())
{
writeRec.write(reinterpret_cast<char *>(&accHolder), sizeof(accHolder));
cout << "\nAccount data successfully written to\n"
<< fileName << " \n";
}
else
{
cout << "FILE ERROR: Could not write account data to " << fileName << "\n"
<< "Returning to main menu ...\n";
}
writeRec.close();
return 0;
}
/* **********************************************************
Definition: getChoice
This function asks the user if he or she wishes to add
another customer account record. The choice is validated
and returned to the caller.
********************************************************** */
char getChoice(const char positive, const char negative)
{
char choice = ' ';
cout << "\n\n\tDo you wish to add another customer account record? ";
cin >> choice;
cin.ignore();
/* Input validation */
while (toupper(choice) != positive && toupper(choice) != negative)
{
cout << "\n\tDo you wish to add another customer account record? ";
cin >> choice;
cin.ignore();
}
return toupper(choice);
}
/* **********************************************************
Definition: readRecord
This function accepts a structure variable passed to it by
reference and a filename as its arguments. It tries to
open a file to read data back in. Upon success, the user
is first asked to enter a record number. The position of
this record is retrieved and the record is displayed. In
case of an error, a message is displayed, and the function
exits to the main menu.
********************************************************** */
int readRecord(AccountData &accHolder, const string fileName)
{
long recNum = 0;
fstream readRec(fileName, ios::in | ios::binary);
/* Upon success, the item record conforming to the input made
by the user is retrieved, and the item information is
displayed. */
if (!readRec.fail())
{
cout << "\nEnter Customer Account Number: ";
cin >> recNum;
cin.ignore();
readRec.seekg((recNum - 1) * sizeof(accHolder));
readRec.read(reinterpret_cast<char *>(&accHolder), sizeof(accHolder));
displayRecord(accHolder);
}
else
{
cout << "\nFILE ERROR: Data could not be read from" << fileName << " ...\n"
<< "Returning to main menu ...\n";
return -1;
}
readRec.close();
return 0;
}
/* **********************************************************
Definition: displayAll
This function accepts a structure variable passed to it by
reference and a filename as its arguments. Upon succes,
the customer account data is read in and displayed. If an
error occurs, a message is displayed, and the function
exits to the main menu.
********************************************************** */
int displayAll(AccountData &accHolder, const string fileName)
{
fstream readRec(fileName, ios::in | ios::binary);
/* Upon success, the item record conforming to the input made
by the user is retrieved, and the item information is
displayed. */
if (!readRec.fail())
{
while(readRec.read(reinterpret_cast<char *>(&accHolder), sizeof(accHolder)))
displayRecord(accHolder);
}
else
{
cout << "\nFILE ERROR: Data could not be read from" << fileName << " ...\n"
<< "Returning to main menu ...\n";
return -1;
}
readRec.close();
return 0;
}
/* **********************************************************
Definition: editRecord
This function accepts a structure variable passed to it
by reference, two char variables, and a filename as its
arguments. It tries to open a file in read and write mode.
Upon succes, the user is asked to enter the record number
he or she wishes to change. This information is retrieved,
the record read in and displayed.
The user is then asked if this is the record he or she
wishes to edit. If the answer is positive, a function that
allows the user to enter data is called. When done, the
user is asked whether the information he or she entered
is correct. If the answer is positive, the item record is
written to file and the function will exit.
In case the user decides that he or she does not wish to
either change a particular record, or finds the record
information is incorrect, the function will exit to the
main menu.
********************************************************** */
int editRecord(AccountData &accHolder, const char positive,
const char negative, const string fileName)
{
long recNum = 0;
char choice = ' ';
fstream alterRec(fileName, ios::in | ios::out | ios::binary);
if (!alterRec.fail())
{
cout << "\nEnter Customer Account Number: ";
cin >> recNum;
alterRec.seekg((recNum -1) * sizeof(accHolder));
alterRec.read(reinterpret_cast<char *>(&accHolder), sizeof(accHolder));
/* Display the customer account information */
displayRecord(accHolder);
cout << "Do you wish to change this customer account record? ";
cin >> choice;
cout << "\n";
choice = toupper(choice);
while (toupper(choice) != positive && toupper(choice) != negative)
{
cout << "Do you wish to change this customer account record? ";
cin >> choice;
cout << "\n";
}
if (toupper(choice) == positive)
{
/* Get new item information */
getAccountData(accHolder);
/* Moves to the position the item record is stored at. */
alterRec.seekp((recNum - 1) * sizeof(accHolder), ios::beg);
/* The user is asked to confirm his or her choice before the changed
record is written to the file. */
cout << "\nIs this information correct? ";
cin >> choice;
cout << "\n";
choice = toupper(choice);
while (toupper(choice) != positive && toupper(choice) != negative)
{
cout << "\nIs this information correct? ";
cin >> choice;
cout << "\n";
choice = toupper(choice);
}
if (toupper(choice) == positive)
{
alterRec.write(reinterpret_cast<char *>(&accHolder), sizeof(accHolder));
}
}
else
{
cout << "\nChoice confirmed. No data has been changed.\n"
<< "Returning to main menu ...\n";
}
}
else
{
cout << "\nFILE ERROR: Data could not be read from or written to " << fileName << "\n"
<< "Now returning to main menu ...\n";
return -1;
}
alterRec.close();
return 0;
}
/* **********************************************************
Definition: deleteRecord
This function accepts a structure variable passed to it
by reference and a filename as its arguments. It tries to
open a file in binary read and write mode. Upon success,
the data is read into memory, and the user is asked to
enter the number of the record he or she wishes to delete.
In case of error, a message is displayed, and the function
returns exits to main menu.
********************************************************** */
int deleteRecord(AccountData &accHolder, const char positive,
const char negative, const string fileName)
{
long recNum = 0;
char choice = ' ';
string tmpFile = "tmpRec.dat";
fstream deleteRec(fileName, ios::in | ios::out | ios::binary);
if (!deleteRec.fail())
{
cin.ignore();
cout << "\nEnter Customer Account Number: ";
cin >> recNum;
deleteRec.seekg((recNum - 1) * sizeof(accHolder));
deleteRec.read(reinterpret_cast<char *>(&accHolder), sizeof(accHolder));
displayRecord(accHolder);
cout << "Do you really wish to delete this customer account record? ";
cin >> choice;
cout << "\n";
choice = toupper(choice);
while (toupper(choice) != positive && toupper(choice) != negative)
{
cout << "Do you really wish to delete this customer account record? ";
cin >> choice;
cout << "\n";
}
if (toupper(choice) == positive)
{
removeRec(accHolder, deleteRec, fileName, tmpFile, recNum);
}
else
{
cout << "\nChoice confirmed. No data has been changed.\n"
<< "Returning to main menu ...\n";
}
}
else
{
cout << "\nFILE ERROR: Data could not be read from or written to " << fileName << "\n"
<< "Now returning to main menu ...\n";
return -1;
}
deleteRec.close();
remove(fileName.c_str());
rename(tmpFile.c_str(), fileName.c_str());
return 0;
}
/* **********************************************************
Definition: removeRec
This function accepts a structure variable passed to it
by reference, an fstream object, two file names, and the
record number to be deleted as its arguments. First, the
record to be eliminated is overwritten with blank data.
It then opens a temporary file for writing. Upon success,
all records holding an account balance greater than 0 are
written to this temporary file, and the function returns
to the main menu. If an error occurs, a message is output
to screen, and the function exits to main menu.
********************************************************** */
int removeRec(AccountData &accHolder, fstream &deleteRec,
const string fileName, const string tmpFile, int recNum)
{
AccountData cleanRec{};
fstream tempRec(tmpFile, ios::out | ios::binary);
deleteRec.seekp((recNum - 1) * sizeof(accHolder), ios::beg);
deleteRec.write(reinterpret_cast<char *>(&cleanRec), sizeof(AccountData));
/* Reset file position to 0 */
deleteRec.clear();
deleteRec.seekg(0L, ios::beg);
if (!tempRec.fail())
{
while (deleteRec.read(reinterpret_cast<char *>(&accHolder), sizeof(accHolder)))
{
if (accHolder.accountBalance > 0)
{
tempRec.write(reinterpret_cast<const char *>(&accHolder), sizeof(accHolder));
}
}
cout << "Record # " << (recNum) << " deleted.\n"
<< "Returning to main menu ...\n";
}
else
{
cout << "\nFILE ERROR: Could not create or write to " << tmpFile << "\n"
<< "Returning to main menu ...\n";
}
tempRec.close();
pauseSystem();
return 0;
}
/* **********************************************************
Definition: displayRecord
This function accepts a reference variable to a struct and
a const string object as arguments. It diplays a single
customer account record.
********************************************************** */
void displayRecord(AccountData &accHolder)
{
cout << "\nAccount ID # " << accHolder.accNumber << "\n"
<< "Name: " << accHolder.name << "\n"
<< "Address: " << accHolder.address << "\n"
<< "City: " << accHolder.city << "\n"
<< "State: " << accHolder.state << "\n"
<< "Zip-Code: " << accHolder.zipCode << "\n"
<< "Telephone # " << accHolder.telephoneNumber << "\n";
cout << fixed << showpoint << setprecision(2);
cout << "Account Balance: JPY " << accHolder.accountBalance << "\n"
<< "Date of Last Payment: " << accHolder.dateLastPayment << "\n\n";
}
Example Output: