C++/c++
Expert: Zlatko - 11/9/2009
QuestionQUESTION: could you pls help mi,i realli realli need your help.i'm hving a veri hard time doing it.i'm trying to keeps track of customers’ portfolios, which include several bank accounts n investments.i'm nt sure whether i'm doing it correct anot,could u pls guide mi.i will be so appericated for all the help frm u.
The first file, customer.txt, has the following format:
customerID firstName lastName address phoneNum Type
10001 Mickey Mouse Sengkang 91111111 Gold ok
50020 Humpty Dumpty JurongWest 94444444 NORmal ok
1001 Ben Jerry JurongEast 93333333 Normal Error, ignore
The second file, account.txt, has the following format:
customerID accountNum type balance numYears
10001 700001 SAVINGS 10000.00 2 ok
10001 70001 SAVINGS 10000.00 2 Error, ignore
The third file, investment.txt, has the following format:
customerID investNum type investValue currValue
10001 3300001 Stock 10000.00 12000.00 ok
50020 33a00 Stock 10000.00 12000.00 Error, ignore
For the three input files above, all fields are not case-sensitive. If any entry has an invalid field, your program will ignore the entry entirely.
For bank accounts, the interest rates are derived based on following table:
CustomerType AccountType
Savings
Normal 1.5%
Gold Normal + 1.0%
Final balance is computed as original balance plus interest earned.
For investment accounts, the gain/loss is computed as the difference between current value and invested value.
output:
*** Overall Customer Statistics ***
Number of customers type Normal: 1
Number of customers type Gold: 1
Total number of customers: 2
*** Individual Customer Statistics ***
*** Customer Particulars ***
Customer ID: 10001
Name: Mickey Mouse
Address: Sengkang
Phone: 91111111
Customer Type: Gold
*** Bank accounts ***
Number: 700001
Type: Savings
Original Balance: $10000.00
Num of years: 2
Interest earned: $500.00
Final Balance: $10500.00
*** Investment accounts ***
Number: 3300001
Type: Stock
Invested value: $10000.00
Current value: $12000.00
Gain/ Loss: $2000.00
code:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
class Customer
{
public:
Customer () {}
void setCustomer(int, string, string, string, int, int);
void display();
private:
int customerID;
string firstName;
string lastName;
string address;
int phoneNum;
int type;
};
void Customer::setCustomer(int id, string fn, string ln, string a, int pn, int ct)
{
customerID = id;
firstName = fn;
lastName = ln;
address = a;
phoneNum = pn;
type = ct;
}
void Customer::display()
{
cout << customerID << '\t' << firstName << '\t' << lastName
<< '\t' << address << '\t' << phoneNum << '\t' << type << endl;
}
class Account
{
public:
Account () {}
void setAccount(int, int, int, int);
void display();
private:
int accountNum;
int type;
int balance;
int numYears;
};
void Account::setAccount(int an, int tp, int bl, int ny)
{
accountNum = an;
type = tp;
balance = bl;
numYears = ny;
}
void Account::display()
{
cout << accountNum << '\t' << type << '\t' << balance
<< '\t' <<numYears << endl;
}
class Investment
{
public:
Investment () {}
void setInvestment(int, int, int, int);
void display();
private:
int investNum;
int type;
int investValue;
int currentValue;
};
void Investment::setInvestment(int in, int tp, int iv, int cv)
{
investNum = in;
type = tp;
investValue = iv;
currentValue = cv;
}
void Investment::display()
{
cout << investNum << '\t' << type << '\t' << investValue
<< '\t' << currentValue << endl;
}
int main()
{
char buffer[256];
ifstream in ("customers.txt");
if (!in.is_open())
{
cout << "Error opening file";
exit (1);
}
while (!in.eof() )
{
in.getline (buffer,100);
cout << buffer << endl;
}
system("pause");
return 0;
}
ANSWER: Hello Lisa.
You've made a good start defining the types of classes you need but you are having trouble reading from the file. I'm going to make some suggestions for the Customer class, then if you like my ideas, you can make similar changes to the other classes. You might also need to save your customers somewhere so you can count them before printing them out. Do you know how to use the standard template vector class? If not, I can help you with that, but the first thing to do is write code to read the files.
You will need these header files:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
I suggest that each class has its own input function to read from its own file. Each class should know how its file is formatted. The main program should not have to worry about that.
For example, the Customer class could have a method like this:
bool read(ifstream& fin);
to read from fin. It reads one customer, and returns true if everything was correct, false otherwise.
The whole class looks like this:
class Customer
{
public:
enum CustomerType
{
Normal = 1,
Gold
};
Customer () {}
void setCustomer(int, string, string, string, int, CustomerType);
void display();
bool read(ifstream& fin);
private:
int customerID;
string firstName;
string lastName;
string address;
int phoneNum;
CustomerType type;
static const int ID_LENGTH = 5;
static const int PHONE_LENGTH = 8;
};
I've made a few additions to your class. I've added constants for the correct ID length and phone length and I'm using an enumeration instead of a plain integer for storing the customer type.
My idea of the read method looks like this:
bool Customer::read(ifstream& fin)
{
// First read individual strings from the file
string idText;
string firstNameText;
string lastNameText;
string addressText;
string phoneText;
string typeText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss(line);
ss >> idText >> firstNameText >> lastNameText >> addressText >> phoneText >> typeText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check names
if (firstNameText.length() == 0) return false;
if (lastNameText.length() == 0) return false;
// Check address
if (addressText.length() == 0) return false;
// Check phone
if (phoneText.length() != PHONE_LENGTH || !allDigits(phoneText)) return false;
// Check customer type
CustomerType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "normal") == 0) inputType = Normal;
else if (strcmp(typeText.c_str(), "gold") == 0) inputType = Gold;
else return false;
// Now assign all inputs to the customer
setCustomer(atoi(idText.c_str()),
firstNameText,
lastNameText,
addressText,
atoi(phoneText.c_str()),
inputType);
return true;
}
Notice that I first read everything into temporary variables that end in "Text". Then I check each input for the correct length, and the correct format. If everything looks OK, then I call setCustomer.
Now you need two helper functions. The function allDigits(const string& input) returns true if the string is all digits, and false otherwise. It looks like this:
bool allDigits(const string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix)
{
if (!isdigit(input[ix])) return false;
}
return true;
}
For strings that are not case sensitive, it is best to put them into lower case with this function:
void toLowerCase(string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix) input[ix] = tolower(input[ix]);
}
The isdigit, and tolower functions are part of the standard C library.
In the main function you can open the customer file, and then have a customer object read the file like this:
int main()
{
ifstream in ("customer.txt");
if (!in.is_open())
{
cout << "Error opening file";
exit (1);
}
Customer c;
while (!in.eof())
{
if (c.read(in)) c.display();
}
}
Good luck. Let me know how it goes.
Kind regards.
Zlatko
---------- FOLLOW-UP ----------
QUESTION: thankz veri much for answering my qns.i realli appericated for all the help frm u.i do nt knw hw to use the standard template vector class.could u pls help mi,as i nt sure whether i hv done correctly for reading all the files.
code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;
class Customer
{
public:
enum CustomerType
{
Normal = 1,
Gold,
Silver,
Platinum
};
Customer () {}
void setCustomer(int, string, string, string, int, CustomerType);
void display();
bool read(ifstream& fin);
void toLowerCase(string&);
bool allDigits(const string& input);
private:
int customerID;
string firstName;
string lastName;
string address;
int phoneNum;
CustomerType type;
static const int ID_LENGTH = 5;
static const int PHONE_LENGTH = 8;
};
class Account
{
public:
enum AccountType
{
Savings = 1,
Checkings,
FixedDeposit
};
Account () {}
void setAccount(int, int, AccountType, int, int);
void display();
bool read(ifstream& fin);
void toLowerCase(string&);
bool allDigits(const string& input);
private:
int customerID;
int accountNum;
int balance;
int numYears;
AccountType type;
static const int ID_LENGTH = 5;
static const int ACCOUNT_LENGTH = 6;
};
class Investment
{
public:
enum InvestmentType
{
Stock = 1,
RealEstate
};
Investment () {}
void setInvestment(int, int, InvestmentType, int, int);
void display();
bool read(ifstream& fin);
void toLowerCase(string&);
bool allDigits(const string& input);
private:
int customerID;
int investNum;
int investValue;
int currValue;
InvestmentType type;
static const int ID_LENGTH = 5;
static const int INVESTNUM_LENGTH = 7;
};
void Customer::setCustomer(int id, string fn, string ln, string a, int pn, CustomerType)
{
customerID = id;
firstName = fn;
lastName = ln;
address = a;
phoneNum = pn;
}
void Customer::display()
{
cout << "*** Individual Customer Statistics ***" << endl;
cout << "*** Customer Particulars ***" << endl;
cout << customerID << ' ' << firstName << ' ' << lastName
<< ' ' << address << ' ' << phoneNum << ' ' << type << endl;
}
bool Customer::read(ifstream& fin)
{
// First read individual strings from the file
string idText;
string firstNameText;
string lastNameText;
string addressText;
string phoneText;
string typeText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> firstNameText >> lastNameText >> addressText >> phoneText >> typeText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check names
if (firstNameText.length() == 0) return false;
if (lastNameText.length() == 0) return false;
// Check address
if (addressText.length() == 0) return false;
// Check phone
if (phoneText.length() != PHONE_LENGTH || !allDigits(phoneText)) return false;
// Check customer type
CustomerType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "normal") == 0) inputType = Normal;
else if (strcmp(typeText.c_str(), "gold") == 0) inputType = Gold;
else if (strcmp(typeText.c_str(), "silver") == 0) inputType = Silver;
else if (strcmp(typeText.c_str(), "platinum") == 0) inputType = Platinum;
else return false;
// Now assign all inputs to the customer
setCustomer(atoi(idText.c_str()),
firstNameText,
lastNameText,
addressText,
atoi(phoneText.c_str()),
inputType);
return true;
}
void Account::setAccount(int id, int an, AccountType, int bl, int ny)
{
customerID = id;
accountNum = an;
balance = bl;
numYears = ny;
}
void Account::display()
{
cout << "*** Bank accounts *** " << endl;
cout << customerID << ' ' << accountNum << ' ' << type << ' ' << balance << ' ' << numYears << endl;
}
bool Account::read(ifstream& fin)
{
// First read individual data from the file
string idText;
string accountNumText;
string typeText;
string balanceText;
string numYearsText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> accountNumText >> typeText >> balanceText >> numYearsText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check AccountNum
if (accountNumText.length() != ACCOUNT_LENGTH || !allDigits(accountNumText)) return false;
// Check account type
AccountType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "savings") == 0) inputType = Savings;
else if (strcmp(typeText.c_str(), "checkings") == 0) inputType = Checkings;
else if (strcmp(typeText.c_str(), "fixed deposit") == 0) inputType = FixedDeposit;
else return false;
// Check balance
if (balanceText.length() == 0) return false;
// Check years
if (numYearsText.length() == 0) return false;
// Now assign all inputs to the account
setAccount(atoi(idText.c_str()),
accountNumText,
inputType,
balanceText,
numYearsText);
return true;
}
void Investment::setInvestment(int id, int in, InvestmentType, int iv, int cv)
{
customerID = id;
investNum = in;
investValue = iv;
currValue = cv;
}
void Investment::display()
{
cout << "*** Bank accounts *** " << endl;
cout << customerID << ' ' << investNum << ' ' << type << ' ' << investValue << ' ' << currValue << endl;
}
bool Investment::read(ifstream& fin)
{
// First read individual data from the file
string idText;
string investNumText;
string typeText;
string investValueText;
string currValueText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> investNumText >> typeText >> investValueText >> currValueText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check AccountNum
if (investNumText.length() != INVESTNUM_LENGTH || !allDigits(investNumText)) return false;
// Check account type
InvestmentType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "stock") == 0) inputType = Stock;
else if (strcmp(typeText.c_str(), "realestate") == 0) inputType = RealEstate;
else return false;
// Check invest value
if (investValueText.length() == 0) return false;
// Check current value
if (currValueText.length() == 0) return false;
// Now assign all inputs to the investment
setInvestment(atoi(idText.c_str()),
investNumText,
inputType,
investValueText,
currValueText);
return true;
}
bool allDigits(const string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix)
{
if (!isdigit(input[ix])) return false;
}
return true;
}
void toLowerCase(string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix) input[ix] = tolower(input[ix]);
}
int main()
{
ifstream in ("customers.txt","account.txt","investment.txt");
if (!in.is_open())
{
cout << "Error opening file";
exit (1);
}
Customer c;
Account a;
Investment i;
while (!in.eof())
{
if (c.read(in)) c.display();
if (a.read(in)) a.display();
if (i.read(in)) i.display();
}
return 0;
}
ANSWER: Hello Lisa.
Your program does not compile. I have made corrections to the program to make it compile. The code is at the very end of this message. Please try to fix your compiler errors before posting your code. If your code compiles, then you can also do some testing and learn how to fix your own errors.
These were the errors:
================================================================
1) You cannot have many characters between single quotes. You cannot have 'xxx'. You need double quotes for that. Like this: "xxx"
2) In many cases you were passing strings to functions that needed integers, you must call atoi(string.c_str()) to convert a string to an integer.
3) Your way of opening files is very creative but wrong. A file stream can access only one file at a time. Please have a look at the main program to see how its done.
4) The toLowerCase and allDigits are not part of any class. They are helper functions for all to use.
Now I have some suggestions:
=================================================================
When dealing with money, you should use floating point numbers instead of integers. You will need to use atof, instead of atoi to convert a string to floating point. You should declare your functions to take doubles for money instead of integers. I will leave that up to you.
When you declare a method, it is good style to show the parameter names in addition to the types.
For example:
void setCustomer(int, string, string, string, int, CustomerType);
is more readable as:
void setCustomer(int id, string fn, string ln, string a, int pn, CustomerType type);
Also, you should use more descriptive variable names.
Output:
=================================================================
The output of the program using my own test files is here below. Notice the number -858993460, it is caused by an uninitialized value in your classes. You must find out what that value is and why it is not being initialized. Ask yourself, what is being printed, where should it be initialized, and why is it not initialized.
*** Individual Customer Statistics ***
*** Customer Particulars ***
10001 Mickey Mouse Sengkang 91111111 -858993460
*** Individual Customer Statistics ***
*** Customer Particulars ***
50020 Humpty Dumpty JurongWest 94444444 -858993460
*** Bank accounts ***
10001 700001 -858993460 10000 2
*** Bank accounts ***
10002 700002 -858993460 10000 2
*** Investments ***
10001 3300001 -858993460 10000 12000
*** Investments ***
10003 3300003 -858993460 10000 13000
Next Steps:
=================================================================
Test the code below with your own files.
If you need to print out the overall customer statistics before the individual customers, you will need to delay printing the individual customers until all your counting is done. You can do the counting while you read in the customers, but then you must store each customer somewhere for printing later. Try storing it in an array. Show me what you come up with.
Best regards.
Zlatko
Code:
=================================================================
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;
bool allDigits(const string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix)
{
if (!isdigit(input[ix])) return false;
}
return true;
}
void toLowerCase(string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix) input[ix] = tolower(input[ix]);
}
class Customer
{
public:
enum CustomerType
{
Normal = 1,
Gold,
Silver,
Platinum
};
Customer () {}
void setCustomer(int, string, string, string, int, CustomerType);
void display();
bool read(ifstream& fin);
private:
int customerID;
string firstName;
string lastName;
string address;
int phoneNum;
CustomerType type;
static const int ID_LENGTH = 5;
static const int PHONE_LENGTH = 8;
};
class Account
{
public:
enum AccountType
{
Savings = 1,
Checkings,
FixedDeposit
};
Account () {}
void setAccount(int, int, AccountType, int, int);
void display();
bool read(ifstream& fin);
private:
int customerID;
int accountNum;
int balance;
int numYears;
AccountType type;
static const int ID_LENGTH = 5;
static const int ACCOUNT_LENGTH = 6;
};
class Investment
{
public:
enum InvestmentType
{
Stock = 1,
RealEstate
};
Investment () {}
void setInvestment(int, int, InvestmentType, int, int);
void display();
bool read(ifstream& fin);
private:
int customerID;
int investNum;
int investValue;
int currValue;
InvestmentType type;
static const int ID_LENGTH = 5;
static const int INVESTNUM_LENGTH = 7;
};
void Customer::setCustomer(int id, string fn, string ln, string a, int pn, CustomerType)
{
customerID = id;
firstName = fn;
lastName = ln;
address = a;
phoneNum = pn;
}
void Customer::display()
{
cout << "*** Individual Customer Statistics ***" << endl;
cout << "*** Customer Particulars ***" << endl;
cout << customerID << ' ' << firstName << " " << lastName
<< " " << address << " " << phoneNum << " " << type << endl;
}
bool Customer::read(ifstream& fin)
{
// First read individual strings from the file
string idText;
string firstNameText;
string lastNameText;
string addressText;
string phoneText;
string typeText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> firstNameText >> lastNameText >> addressText >> phoneText >> typeText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check names
if (firstNameText.length() == 0) return false;
if (lastNameText.length() == 0) return false;
// Check address
if (addressText.length() == 0) return false;
// Check phone
if (phoneText.length() != PHONE_LENGTH || !allDigits(phoneText)) return false;
// Check customer type
CustomerType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "normal") == 0) inputType = Normal;
else if (strcmp(typeText.c_str(), "gold") == 0) inputType = Gold;
else if (strcmp(typeText.c_str(), "silver") == 0) inputType = Silver;
else if (strcmp(typeText.c_str(), "platinum") == 0) inputType = Platinum;
else return false;
// Now assign all inputs to the customer
setCustomer(atoi(idText.c_str()),
firstNameText,
lastNameText,
addressText,
atoi(phoneText.c_str()),
inputType);
return true;
}
void Account::setAccount(int id, int an, AccountType, int bl, int ny)
{
customerID = id;
accountNum = an;
balance = bl;
numYears = ny;
}
void Account::display()
{
cout << "*** Bank accounts *** " << endl;
cout << customerID << ' ' << accountNum << " " << type << " " << balance << " " << numYears << endl;
}
bool Account::read(ifstream& fin)
{
// First read individual data from the file
string idText;
string accountNumText;
string typeText;
string balanceText;
string numYearsText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> accountNumText >> typeText >> balanceText >> numYearsText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check AccountNum
if (accountNumText.length() != ACCOUNT_LENGTH || !allDigits(accountNumText)) return false;
// Check account type
AccountType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "savings") == 0) inputType = Savings;
else if (strcmp(typeText.c_str(), "checkings") == 0) inputType = Checkings;
else if (strcmp(typeText.c_str(), "fixed deposit") == 0) inputType = FixedDeposit;
else return false;
// Check balance
if (balanceText.length() == 0) return false;
// Check years
if (numYearsText.length() == 0) return false;
// Now assign all inputs to the account
setAccount(atoi(idText.c_str()),
atoi(accountNumText.c_str()),
inputType,
atoi(balanceText.c_str()),
atoi(numYearsText.c_str()));
return true;
}
void Investment::setInvestment(int id, int in, InvestmentType, int iv, int cv)
{
customerID = id;
investNum = in;
investValue = iv;
currValue = cv;
}
void Investment::display()
{
cout << "*** Investments *** " << endl;
cout << customerID << ' ' << investNum << " " << type << " " << investValue << " " << currValue << endl;
}
bool Investment::read(ifstream& fin)
{
// First read individual data from the file
string idText;
string investNumText;
string typeText;
string investValueText;
string currValueText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> investNumText >> typeText >> investValueText >> currValueText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check AccountNum
if (investNumText.length() != INVESTNUM_LENGTH || !allDigits(investNumText)) return false;
// Check account type
InvestmentType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "stock") == 0) inputType = Stock;
else if (strcmp(typeText.c_str(), "realestate") == 0) inputType = RealEstate;
else return false;
// Check invest value
if (investValueText.length() == 0) return false;
// Check current value
if (currValueText.length() == 0) return false;
// Now assign all inputs to the investment
setInvestment(atoi(idText.c_str()),
atoi(investNumText.c_str()),
inputType,
atoi(investValueText.c_str()),
atoi(currValueText.c_str()));
return true;
}
int main()
{
ifstream customers("customers.txt");
ifstream accounts("account.txt");
ifstream investments("investment.txt");
if (!customers.is_open())
{
cout << "Error opening customer file";
exit (1);
}
if (!accounts.is_open())
{
cout << "Error opening accounts file";
exit (1);
}
if (!investments.is_open())
{
cout << "Error opening investments file";
exit (1);
}
Customer c;
while (!customers.eof())
{
if (c.read(customers)) c.display();
}
Account a;
while (!accounts.eof())
{
if (a.read(accounts)) a.display();
}
Investment i;
while (!investments.eof())
{
if (i.read(investments)) i.display();
}
return 0;
}
---------- FOLLOW-UP ----------
QUESTION: could u pls help mi.i will be so greatly appericated for all the help frm u.i trying to do the static for the customers.wen i compile i keep hving errors.i realli do nt knw y.
code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;
class Customer
{
public:
static int numType;
enum CustomerType
{
Normal=1,
Gold,
Silver,
Platinum
};
Customer () {}
void setCustomer(int, string, string, string, int, CustomerType);
void display();
bool read(ifstream& fin);
private:
int customerID;
string firstName;
string lastName;
string address;
int phoneNum;
CustomerType type;
static const int ID_LENGTH = 5;
static const int PHONE_LENGTH = 8;
};
int Customer::numType = 0;
void Customer::setCustomer(int id, string fn, string ln, string a, int pn, CustomerType ct)
{
customerID = id;
firstName = fn;
lastName = ln;
address = a;
phoneNum = pn;
type = ct;
}
void Customer::display()
{
cout << endl;
cout << "*** Individual Customer Statistics ***" << endl;
cout << "*** Customer Particulars ***" << endl;
cout << "CustomerID: " << customerID << ' ' << "
Name: " << firstName << " " << lastName << " "
<< "
Address: " << address << " " << "
Phone: " << phoneNum << " " << "
Customer Type: " << type << endl;
switch(type)
{
case Normal: cout << "Normal
";
break;
case Gold: cout << "Gold
";
break ;
case Silver: cout << "Silver
";
break;
case Platinum: cout << "Platinum
";
break;
default: cout << "invalid value
";
}
}
bool allDigits(const string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix)
{
if (!isdigit(input[ix])) return false;
}
return true;
}
void toLowerCase(string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix) input[ix] = tolower(input[ix]);
}
bool Customer::read(ifstream& fin)
{
// First read individual strings from the file
string idText;
string firstNameText;
string lastNameText;
string addressText;
string phoneText;
string typeText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> firstNameText >> lastNameText >> addressText >> phoneText >> typeText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check names
if (firstNameText.length() == 0) return false;
if (lastNameText.length() == 0) return false;
// Check address
if (addressText.length() == 0) return false;
// Check phone
if (phoneText.length() != PHONE_LENGTH || !allDigits(phoneText)) return false;
// Check customer type
CustomerType inputType;
toLowerCase(typeText);
if(typeText == "normal")inputType = Normal;
else if (typeText =="gold")inputType = Gold;
else if (typeText == "silver")inputType = Silver;
else if (typeText == "platinum")inputType = Platinum;
else return false;
// Now assign all inputs to the customer
setCustomer(atoi(idText.c_str()),
firstNameText,
lastNameText,
addressText,
atoi(phoneText.c_str()),
inputType);
return true;
}
void readFile(Customer[]);
void DisplayCustomer(Customer customerList[]);
int main()
{
Customer customerList[6];
int customerTotal = 0;
char temp;
int customerID,firstName,lastName,address,phoneNum,type;
readFile(customerList);
customerList[customerTotal] = *new Customer(customerID,firstName,lastName,address,phoneNum,type);
customerTotal++;
DisplayCustomer(customerList);
system("pause");
return 0;
}
void readFile(Customer customerList[])
{
int num;
int customerTotal = 0;
int customerID,firstName,lastName,address,phoneNum,type;
ifstream customers;
customers.open("customers.txt");
if (!customers.good())
{
cout << "File not found" << endl;
exit(1);
}
num = Customer::numType;
Customer::numType++;
customerList[customerTotal] = *new Customer(customerID,firstName,lastName,address,phoneNum,type);
customerTotal++;
customers.close();
}
void DisplayCustomer(Customer customerList[])
{
int num = Customer::numType;
cout << "===================================" << endl;
cout << "*** Overall Customer Statistics ***" << endl;
cout << "Number of customers type Normal: " << num << endl;
cout << "Number of customers type Silver: " << num << endl;
cout << "Number of customers type Gold: " << num << endl;
cout << "Number of customers type Platinum: " << num << endl;
cout << "Total number of customers: " << num << endl;
cout << endl;
}
AnswerHello Lisa.
Please make sure you read my suggestion at the end before making changes to your code.
Here are the problems I found:
============================================================================
First lets correct the syntax errors. In many places you have a string that spans multiple lines. For example:
case Normal: cout << "Normal
";
break;
You see how the ending quote is on a different line from the starting quote. Did you do that or did the AllExperts web site make it that way?
The correction looks like this:
case Normal: cout << "Normal";
break;
After I corrected those errors, my compiler told me that the next error is in the main function, where you are doing:
customerList[customerTotal] = *new Customer(customerID,firstName,lastName,address,phoneNum,type);
You are trying to call a Customer constructor with 6 arguments, but you do not have such a constructor. The constructor should look much like your setCustomer method. Can you make such a constructor on your own?
Where are you planning to read the file? You are no longer calling Customer::read. If you want to call a Customer constructor with the ID, name, address, etc, you will need to read those items in before calling the constructor.
I don't understand what Customer::numType is for. It seems to be the same as customerTotal.
You have this line:
customerList[customerTotal] = *new Customer(customerID,firstName,lastName,address,phoneNum,type);
in both main, and in readFile. You should make up your mind about which function will have the job of creating the customer.
My suggestion:
============================================================================
I would suggest that you forget about the 6 argument Customer constructor, and go back to the Customer::read method. The previous version of the program I sent you was almost working. Simply do this:
int customerTotal = 0;
Customer c;
while (!customers.eof())
{
if (c.read(customers))
{
customerList[customerTotal++] = c;
}
}
The customer c will be copied into the array. There is no need to do a "new" here. Also, in case you're wondering about copy constructors, you do not need a copy constructor here. The copy will be done automatically.
Once you have the customers in the array, go over the array again and count the number of customers of each type.
Print out the number of customers of each type, then go over the array again and print out the individual customers.
Then go on to do the bank accounts and investment accounts.
======================================================================================
======================================================================================
Edit November 9, 8:00 EST
======================================================================================
======================================================================================
Hello Lisa. I hope I haven't frustrated you. If I've confused you, I am sorry. I am trying to guide you through the process of learning how to solve these problems yourself. If you do not learn for yourself, you will have trouble on your exams. However, I do remember what it's like to be a student, and I know you have many pressures. So, I am going to give a working solution to you assignment. It will be up to your to test it with your files, and to format the output the way you want it. I am using vectors, instead of arrays to store customers, accounts, and investments. If you have any questions, please ask.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
bool allDigits(const string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix)
{
if (!isdigit(input[ix])) return false;
}
return true;
}
void toLowerCase(string& input)
{
for(size_t ix = 0; ix < input.size(); ++ix) input[ix] = tolower(input[ix]);
}
class Customer
{
public:
enum CustomerType
{
Normal = 1,
Gold,
Silver,
Platinum
};
Customer () {}
void setCustomer(int, string, string, string, int, CustomerType);
void display();
bool read(ifstream& fin);
CustomerType getType(void) const { return type; }
private:
int customerID;
string firstName;
string lastName;
string address;
int phoneNum;
CustomerType type;
static const int ID_LENGTH = 5;
static const int PHONE_LENGTH = 8;
};
class Account
{
public:
enum AccountType
{
Savings = 1,
Checkings,
FixedDeposit
};
Account () {}
void setAccount(int, int, AccountType, int, int);
void display();
bool read(ifstream& fin);
private:
int customerID;
int accountNum;
int balance;
int numYears;
AccountType type;
static const int ID_LENGTH = 5;
static const int ACCOUNT_LENGTH = 6;
};
class Investment
{
public:
enum InvestmentType
{
Stock = 1,
RealEstate
};
Investment () {}
void setInvestment(int, int, InvestmentType, int, int);
void display();
bool read(ifstream& fin);
private:
int customerID;
int investNum;
int investValue;
int currValue;
InvestmentType type;
static const int ID_LENGTH = 5;
static const int INVESTNUM_LENGTH = 7;
};
void Customer::setCustomer(int id, string fn, string ln, string a, int pn, CustomerType t)
{
customerID = id;
firstName = fn;
lastName = ln;
address = a;
phoneNum = pn;
type = t;
}
void Customer::display()
{
cout << "*** Individual Customer Statistics ***\n";
cout << "*** Customer Particulars ***" << endl;
cout << customerID << ' ' << firstName << " " << lastName
<< " " << address << " " << phoneNum << " " << type << endl;
}
bool Customer::read(ifstream& fin)
{
// First read individual strings from the file
string idText;
string firstNameText;
string lastNameText;
string addressText;
string phoneText;
string typeText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> firstNameText >> lastNameText >> addressText >> phoneText >> typeText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check names
if (firstNameText.length() == 0) return false;
if (lastNameText.length() == 0) return false;
// Check address
if (addressText.length() == 0) return false;
// Check phone
if (phoneText.length() != PHONE_LENGTH || !allDigits(phoneText)) return false;
// Check customer type
CustomerType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "normal") == 0) inputType = Normal;
else if (strcmp(typeText.c_str(), "gold") == 0) inputType = Gold;
else if (strcmp(typeText.c_str(), "silver") == 0) inputType = Silver;
else if (strcmp(typeText.c_str(), "platinum") == 0) inputType = Platinum;
else return false;
// Now assign all inputs to the customer
setCustomer(atoi(idText.c_str()),
firstNameText,
lastNameText,
addressText,
atoi(phoneText.c_str()),
inputType);
return true;
}
void Account::setAccount(int id, int an, AccountType t, int bl, int ny)
{
customerID = id;
accountNum = an;
balance = bl;
numYears = ny;
type = t;
}
void Account::display()
{
cout << "*** Bank accounts *** " << endl;
cout << customerID << ' ' << accountNum << " " << type << " " << balance << " " << numYears << endl;
}
bool Account::read(ifstream& fin)
{
// First read individual data from the file
string idText;
string accountNumText;
string typeText;
string balanceText;
string numYearsText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> accountNumText >> typeText >> balanceText >> numYearsText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check AccountNum
if (accountNumText.length() != ACCOUNT_LENGTH || !allDigits(accountNumText)) return false;
// Check account type
AccountType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "savings") == 0) inputType = Savings;
else if (strcmp(typeText.c_str(), "checkings") == 0) inputType = Checkings;
else if (strcmp(typeText.c_str(), "fixed deposit") == 0) inputType = FixedDeposit;
else return false;
// Check balance
if (balanceText.length() == 0) return false;
// Check years
if (numYearsText.length() == 0) return false;
// Now assign all inputs to the account
setAccount(atoi(idText.c_str()),
atoi(accountNumText.c_str()),
inputType,
atoi(balanceText.c_str()),
atoi(numYearsText.c_str()));
return true;
}
void Investment::setInvestment(int id, int in, InvestmentType t, int iv, int cv)
{
customerID = id;
investNum = in;
investValue = iv;
currValue = cv;
type = t;
}
void Investment::display()
{
cout << "*** Investments *** " << endl;
cout << customerID << ' ' << investNum << " " << type << " " << investValue << " " << currValue << endl;
}
bool Investment::read(ifstream& fin)
{
// First read individual data from the file
string idText;
string investNumText;
string typeText;
string investValueText;
string currValueText;
// Read the entire line in, then create a string stream from the line.
// The string stream will break the line down into its pieces.
string line;
getline(fin, line);
istringstream ss (line);
ss >> idText >> investNumText >> typeText >> investValueText >> currValueText;
// Now check that each input is valid
// Check ID
if (idText.length() != ID_LENGTH || !allDigits(idText)) return false;
// Check AccountNum
if (investNumText.length() != INVESTNUM_LENGTH || !allDigits(investNumText)) return false;
// Check account type
InvestmentType inputType;
toLowerCase(typeText);
if (strcmp(typeText.c_str(), "stock") == 0) inputType = Stock;
else if (strcmp(typeText.c_str(), "realestate") == 0) inputType = RealEstate;
else return false;
// Check invest value
if (investValueText.length() == 0) return false;
// Check current value
if (currValueText.length() == 0) return false;
// Now assign all inputs to the investment
setInvestment(atoi(idText.c_str()),
atoi(investNumText.c_str()),
inputType,
atoi(investValueText.c_str()),
atoi(currValueText.c_str()));
return true;
}
int main()
{
////////////////////////////////////////////////////////
// Open files
////////////////////////////////////////////////////////
ifstream customerFile("customers.txt");
ifstream accountFile("account.txt");
ifstream investmentFile("investment.txt");
if (!customerFile.is_open())
{
cout << "Error opening customer file";
exit (1);
}
if (!customerFile.is_open())
{
cout << "Error opening accounts file";
exit (1);
}
if (!investmentFile.is_open())
{
cout << "Error opening investments file";
exit (1);
}
////////////////////////////////////////////////////////
// Read in files
////////////////////////////////////////////////////////
vector<Customer> customers;
vector<Account> accounts;
vector<Investment> investments;
Customer c;
while (!customerFile.eof())
{
if (c.read(customerFile)) customers.push_back(c);
}
Account a;
while (!customerFile.eof())
{
if (a.read(customerFile)) accounts.push_back(a);
}
Investment i;
while (!investmentFile.eof())
{
if (i.read(investmentFile)) investments.push_back(i);
}
////////////////////////////////////////////////////////
// Print out overall statistics
////////////////////////////////////////////////////////
int gold = 0;
int platinum = 0;
int silver = 0;
int normal = 0;
for (size_t i = 0; i < customers.size(); ++i)
{
switch(customers[i].getType())
{
case Customer::Gold: ++gold; break;
case Customer::Platinum: ++platinum; break;
case Customer::Silver: ++silver; break;
case Customer::Normal: ++normal; break;
}
}
cout << "*** Overall Customer Statistics ***\n";
cout << "Number of customers type Normal: " << normal << endl;
cout << "Number of customers type Gold: " << gold << endl;
cout << "Number of customers type Platinim: " << platinum << endl;
cout << "Number of customers type Silver: " << silver << endl;
cout << endl;
////////////////////////////////////////////////////////
// Print out individual customers
////////////////////////////////////////////////////////
for (size_t i = 0; i < customers.size(); ++i)
{
customers[i].display();
}
////////////////////////////////////////////////////////
// Print out bank accounts
////////////////////////////////////////////////////////
for (size_t i = 0; i < accounts.size(); ++i)
{
accounts[i].display();
}
////////////////////////////////////////////////////////
// Print out investment accounts
////////////////////////////////////////////////////////
for (size_t i = 0; i < investments.size(); ++i)
{
investments[i].display();
}
return 0;
}