hi I write this following code after I debug when I try to read inside of my file after reading data when it returns from (printdata()) function i witness the following error can any one help me about this error?
Unhandled exception at 0x0F50DF58 : 0xC0000005: Access violation reading location 0x0047CA04.
////////////Library.h
#include <string>
using namespace std;
class Library
{
private:
string BookName;
string Author;
int Day,Month,Year ; //day month year
float Price;
string Subject;
double ISBN;
public:
Library(string = "", string = "", int = 0, int = 0, int = 0, float = 0.0, string = "", double = 0.0);
void setBookName(string);
void setAuthor(string);
void setPurchaseDay(int );
void setPurchaseMonth(int);
void setPurchaseYear(int);
void setPrice(float);
void setSubject(string);
void setISBN(double);
string getBookName();
string getAuthor();
int getPurchaseDay();
int getPurchaseMonth();
int getPurchaseYear();
float getPrice();
string getSubject();
double getISBN();
};
///////Linrary.cpp
#include "stdafx.h"
#include "Library.h"
#include <iostream>
#include <string>
using namespace std;
Library::Library(string bookname, string author,int day,int month,int year, float price, string subject, double isbn)
{
setBookName(bookname);
setAuthor(author);
setPurchaseDay(day);
setPurchaseMonth(month);
setPurchaseYear(year);
setPrice(price);
setSubject(subject);
setISBN(isbn);
}
void Library::setBookName(string bookname)
{
BookName = bookname;
}
void Library::setAuthor(string author)
{
Author = author;
}
void Library::setPurchaseDay( int day)
{
Day = day;
}
void Library::setPurchaseMonth(int month)
{
Month = month;
}
void Library::setPurchaseYear(int year)
{
Year = year;
}
void Library::setPrice(float price)
{
Price = price;
}
void Library::setSubject(string subject)
{
Subject = subject;
}
void Library::setISBN(double isbn)
{
ISBN = isbn;
}
///////////////////////////////////////////////
string Library::getBookName()
{
return BookName;
}
string Library::getAuthor()
{
return Author;
}
int Library::getPurchaseDay()
{
return Day;
}
int Library::getPurchaseMonth()
{
return Month;
}
int Library::getPurchaseYear()
{
return Year;
}
float Library::getPrice()
{
return Price;
}
string Library::getSubject()
{
return Subject;
}
double Library::getISBN()
{
return ISBN;
}
////////main function
#include "stdafx.h"
#include "Library.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;
int menu();
void EnterData();
void PrintData();
int main(int argc, char *arg[])
{
for (;;)
{
system("cls");
int c = menu();
switch (c)
{
case 1:
EnterData();
break;
case 2:
PrintData();
break;
case 8:
exit(0);
}//end of switch
}//end of for
}
int menu()
{
int p;
do
{
cout << "1. Enter Data of a Book." << endl;
cout << "2. Print Data of all Books." << endl;
cout << "3. Search a Book by Subject." << endl;
cout << "4. Search a Book by Auther." << endl;
cout << "5. Pirnt Books Purchased in a Period of Time." << endl;
cout << "6. Search by ISBN." << endl;
cout << "7. Price of Books Purchased in a Period of Time." << endl;
cin >> p;
} while (p < 0 || p>7);
cin.get();
return p;
}//end of menu() function
//***************Enter Data to File****************8
void EnterData()
{
system("cls");
ofstream fp("LIB.txt", ios::out | ios::trunc);
if (!fp)
{
cerr << "\nError in opening file to write in...";
cin.get();
exit(1);
}
Library data1;
cout << "\nEnter data of the book and write '.' instead of name to finilize."<<endl<<endl;
string bookname, author, subject;
int day, month, year;
float price;
double isbn;
do{
cout << "\nBook Name: ";
getline(cin, bookname);
data1.setBookName(bookname);
if (bookname == ".")
{
author = ".";
subject = ".";
price = 0.0;
isbn = 0;
day = month = year = 0;
data1.setAuthor(author);
data1.setSubject(subject);
data1.setPrice(price);
data1.setISBN(isbn);
data1.setPurchaseDay(day);
data1.setPurchaseMonth(month);
data1.setPurchaseYear(year);
fp.write((char*)(&data1), sizeof(Library));
return;
}
cout << "\nAuthor: ";
getline(cin, author);
data1.setAuthor(author);
cout << "\nPurchase Date (day,month,year): ";
cin >> day;
cin >> month;
cin >> year;
cin.ignore();
data1.setPurchaseDay(day);
data1.setPurchaseMonth(month);
data1.setPurchaseYear(year);
cout << "\nPrice: ";
cin >> price;
data1.setPrice(price);
cin.ignore();
cout << "\nSubject: ";
getline(cin, subject);
data1.setSubject(subject);
cout << "\nISBN: ";
cin >> isbn;
data1.setISBN(isbn);
cin.ignore();
fp.write((char*)(&data1), sizeof(Library));
} while (1);
fp.close();
cin.get();
}//enter of enterdata() function
//***************Print Data********************
void PrintData()
{
system("cls");
ifstream fp("LIB.txt", ios::in);
if (!fp)
{
cerr << "\nError in opening file to write in...";
cin.get();
exit(2);
}
Library data2;
string bookname, author, subject;
int day, month, year;
float price;
double isbn;
cout << left << setw(12) << "BookName" << setw(12) << "Author" << setw(12) << "PurchaseDate"
<< right<<setw(7) << "Price" << setw(12) << "Subject" << setw(7) << "ISBN"<<endl;
cout << "____________________________________________________________________"<<endl;
fp.read((char *)(&data2), sizeof(Library));
while ( fp && !fp.eof())
{
bookname=data2.getBookName();
author=data2.getAuthor();
day=data2.getPurchaseDay();
month = data2.getPurchaseMonth();
year = data2.getPurchaseYear();
price = data2.getPrice();
isbn = data2.getISBN();
subject = data2.getSubject();
//cout << left << setw(12) << bookname << setw(12) << author << setw(12) << purchasedate[0] << purchasedate[1] << purchasedate[2]
//<< right << setw(7) << price << setw(12) << subject << setw(7) << isbn << endl;
if (bookname.at(0) == '.')
{
fp.close();
break;
}
fp.read((char *)(&data2), sizeof(Library));
}
cin.get();
//fp.close();
//return;
}
disclaimer I am by no means a C programmer, and very well may be wrong here.
Your issues is probably coming from here:
fp.write((char*)(&data1), sizeof(Library));
You are passing the method data1, but telling it that the size of the file it should write is the size of Library, where it should be the size of data.
Library, being larger then data1, will cause a buffer overrun, where you will try reading a memory address outside of your application / variable.
Related
I'm making this program using a class named animal, below is the code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include "animal.h"
using namespace std;
int main() {
animal moke;
ofstream out;
out.open("/Users/Abel/Desktop/Cpp/animal/animal/animalRecords.txt");
vector<animal> monke;
bool quit = false;
while (!quit) {
int choice;
cout << "1. Add info for animals 2. Edit Info for animals 3. Exit\n";
cin >> choice;
string nam;
string spec;
int ag;
int editRow;
//menu
switch (choice) {
case 1:
cout << "Enter the Animal's name\n";
cin >> nam;
moke.setName(nam);
cout << "Enter the Species\n";
cin >> spec;
moke.setSpecies(spec);
cout << "Enter the age\n";
cin >> ag;
moke.setAge(ag);
monke.push_back(moke);
break;
case 2:
if(monke.size() == 0) {
cout << "Nothing to modify";
}
else {
for (int i = 0; i < monke.size(); i++) {
cout << i+1 << "\t\tName = " << monke[i].getName() << "\tSpecies = " << monke[i].getSpecies() << "\tAge = " << monke[i].getAge() << endl;
}
cout << "Which row would you like to edit\n";
cin >> editRow;
if (editRow > monke.size() || editRow < 1) {
cout << "Please follow directions\n";
}
else {
cout << "1. Edit name\t2. Edit species\t3. Edit age\n";
cin >> choice;
switch(choice) {
case 1:
cout << "Enter the new name\n";
cin >> nam;
monke[editRow-1].setName(nam);
break;
case 2:
cout << "Enter the new species\n";
cin >> spec;
monke[editRow-1].setSpecies(spec);
break;
case 3:
cout << "Enter the new age\n";
cin >> ag;
monke[editRow-1].setAge(ag);
break;
default:
cout << "You need to learn how to follow instruction <:(\n";
}
}
}
break;
case 3:
if (monke.size() == 0) {
cout << "Bye\n";
}
else {
for (int i = 0; i < monke.size(); i++)
out << i+1 << "\t\tName = " << monke[i].getName() << "\tSpecies = " << monke[i].getSpecies() << "\tAge = " << monke[i].getAge() << endl;
}
break;
default:
cout << "You are so basic\n";
break;
}
}
}
#pragma once
#include <string>
using namespace std;
class animal{
public:
animal();
animal(string name, string species, int age);
animal(animal &E);
void setName(string name);
void setSpecies(string species);
void setAge(int age);
string getName();
string getSpecies();
int getAge();
private:
string n, s;
int a;
};
#include "animal.h"
#include <string>
using namespace std;
animal::animal() {
n = "";
s = "";
a = 0;
}
animal::animal(string name, string species, int age) {
n = name;
s = species;
a = age;
}
animal::animal(animal &E) {
a = E.a;
s = E.s;
s = E.s;
}
void animal::setName(string name) {
n = name;
}
void animal::setSpecies(string species) {
s = species;
}
void animal::setAge(int age) {
a = age;
}
string animal::getName() {
return n;
}
string animal::getSpecies() {
return s;
}
int animal::getAge() {
return a;
}
When running this, it shows these errors:
No matching constructor for initialization of 'animal'
is_cpp17_move_insertable<std::allocator<animal>, void>::value' "The specified type does not meet the requirements of Cpp17MoveInsertable"
No matching constructor for initialization of 'animal'
I have a program to create a phone book in a file. Some of my functions don't work or don't work properly.
user.h
#pragma once
#include <string>
#include <vector>
using namespace std;
class User
{private:
string firstname, lastname, country, city, street;
string phone;
public:
string prefix;
void ReadAllUsers(User[], int&);
void SaveUser(User, int&);
void SaveToFile(const User[], int);
void AddName(User[], int&);
void ListAllUsers(const User[], int&);
void Prefix(User, int);
void ChangePhone(User[], int&);
void Help();
void DeleteUser(User[], int&);
bool Search(string x)
{
return (phone.find(x) != string::npos);
}
};
user.cpp
#include "User.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#pragma warning(disable:4996)
using namespace std;
const string PHONEBOOK_FILENAME = "phonebook.txt";
void User::Help()
{cout<<"\nWELCOME TO THE APPLICATION!\n";
cout<<"Press 0 to display on the screen all records that are saved in the file(phonebook.txt)\n";
cout<<"Press 1 to add 1 or more new record(s) in file(phonebook.txt)\n";
cout<<"Press 2 to delete permanently a record from file(phonebook.txt)\n";
cout<<"Press 3 to sort users from file(phonebook.txt) by name and display them on the screen\n";
cout<<"Press 4 to edit a user phone number and save it after in file(phonebook.txt)\n";
cout<<"Press 5 for help\n";
cout<<"Press 6 to exit the application\n";
}
void User::ReadAllUsers(User people[], int &num_people)
{
ifstream f;
f.open(PHONEBOOK_FILENAME.c_str());
if (f.fail())
{
cout << "Unable to open file " << endl;
return ;
}
int i = 0;
while (!f.eof() && i < 100)
{ getline(f, people[i].firstname);
getline(f, people[i].lastname);
getline(f, people[i].phone);
getline(f, people[i].country);
getline(f, people[i].city);
getline(f, people[i].street);
i++;
}
num_people = i;
f.close();
}
//Add country prefix to the phone number
void User::Prefix(User person, int num_people)
{string filecountry;
ifstream f;
f.open("prefix.txt");
{
while (getline(f, filecountry))
{
if (person.country == filecountry )
{
f.ignore();//next line
f >> person.prefix;
}
}
f.close();
}
}
void User::SaveUser(User person, int &num_people)
{
ofstream f(PHONEBOOK_FILENAME.c_str(), ios::app ) ;
if (f.fail())
cout << "Unable to open file " << endl;
else
f << person.firstname << " " << person.lastname << " " << person.country << " " << person.city << " " << person.street << " " << person.prefix << "-" << person.phone << endl;
cout << "\nThe user was added\n";
}
//Save data after a modification or after a user delete
void User::SaveToFile(const User people[], int num_people)
{ofstream f;
f.open(PHONEBOOK_FILENAME.c_str());
for(int i = 0; i < num_people; i++)
{
f << people[i].firstname << " " << people[i].lastname << " " << people[i].country << " " << people[i].city << " " << people[i].street << " " << people[i].prefix << " " << people[i].phone << endl;
}
}
// Read user data from the keyboard, add a new contact to the array
void User::AddName(User people[],int &num_people)
{User person;
cout <<"Enter the user's first name: ";
cin >> person.firstname;
cout <<"Enter the user's last name: ";
cin >> person.lastname;
cout <<"Enter the user's country: ";
cin >> person.country;
cout <<"Enter the user's city: ";
cin >> person.city;
cout <<"Enter the user's street: ";
cin >> person.street;
cout <<"Enter the user's phone number: ";
cin >> person.phone;
Prefix(person, num_people);
cout <<"The prefix is " << person.prefix;
for(int i = 0; i < num_people; i++)
{
if( i + 1 == num_people)
people[num_people] = person;
}
SaveUser(person, num_people);
num_people++;
}
// Ask the for person's name to change, find the person in the array and
// change it to the new phone number. Then save the new data to file by
// calling SaveToFile.
void User::ChangePhone(User people[], int &num_people)
{
User person;
int count;
cout <<"Enter name to change: ";
cin >> person.firstname;
for(count = 0; count < num_people; count++)
{
if(people[count].Search(person.firstname))
{ cout <<endl<< people[count].firstname<<endl;
cout <<"Current number"<<people[count].phone;
cout << "\nNew number: ";
cin >> people[count].phone;
SaveToFile(people,num_people);
cout <<"\n\nNew number Saved.";
return;
}
}
if(count = num_people)
cout <<"\nName not found.\n";
}
void User::DeleteUser(User people[], int &num_people)
{string phone;
int count = 0;
ifstream f;
f.open("phonebook.txt");
cout << "Input the phone of user that you want to delete ";
cin >> phone;
for(count = 0; count < num_people; count++)
{
if(people[count].Search(phone))
{ cout <<endl<< people[count].phone<<endl;
people[count].firstname = people[count].lastname = people[count].phone = people[count].country = people[count].city = people[count].street = " ";
}
SaveToFile(people,num_people);
cout <<"\n\nUser deleted.";
return;}
f.close();
}
The function Prefix()(this is to add automatically a country prefix for phone number, this is read from a file) is working but the value of person.prefix it's not taken by SaveUser(), so the value is not wrote in file.The function SaveToFile() save all users on single line in file.
And functions ChangePhone() and DeleteUser don't working.
The problem is that void User::Prefix(User person, int num_people) takes person by value, so it makes a copy of the person, changes the copy, then the copy goes away when the function ends. The original was never changed.
Instead, you want:
void User::Prefix(User & person, int num_people)
To have a reference to the person specified, which will be affected by the changes you make inside the function.
Also, I recommend you change your saveuser to be:
void User::SaveUser(User const & person, int &num_people) const
just to avoid making extra copies of the User object, but it's not incorrect the way you currently have it, I don't think.
For my project, my program has to read a file that looks like this: "Mary", "000111222", "Junior", 12, 4.0
In my main code it can read it, but only as strings only. I want it to read it as string,string, string, float, float. The getLine() method only works with strings. I tried other ways but it did not work. Any suggestions? The fields I want to be a float is gpa and credit. Any advice is appreciated! Thank you!
#include <iostream>
#include <string>
#include <iterator>
#include <iomanip>
#include <fstream>
#include <vector>
include <sstream>
#include <algorithm>
using namespace std;
class Student {
//declare local variables
protected:
string name; //people with names longer than 21 characters will just have
to make do
string ssn; // Social Secturity Number.
string gpa; //Most up to date gpa for the student
string credits; //Number of student's credit hours
//build public methods
public:
//Default Constructor
Student() {}
//Student constructor. Besides the character arrays, everything else is
passed by reference.
Student(const string n, const string s, string sGPA, string sCredits) {
name = n;
ssn = s;
gpa = sGPA;
credits = sCredits;
}
string getName() {
return name;
}
string getSSN() {
return ssn;
}
string getGPA() {
return gpa;
}
string getCredit() {
return credits;
}
//a function that is expected to be implemented and overridden by subclasses
virtual void print() const {
cout << '\n' << endl;
cout << "Student's name: " << name << endl;
cout << "Student SSN: " << ssn << endl;
cout << "Student's current GPA: " << gpa << endl;
cout << "Student's credit hours: " << credits << endl;
}
// a pure virtual function for implementation later. Makes whole class
Abstract
virtual float tuition() const = 0;
};
class Undergrad : public Student {
//declare local variables
protected:
float undergrad_rate = 380.0;
string year;
//build public methods
public:
//Default Constructor
Undergrad() {}
//Undergrad Constructor
Undergrad(const string n, const string s, string uGPA, string uCredits,
string y) :
Student(n, s, uGPA, uCredits), year(y) {}
//Display the contents of undergrad
void print() const {
Student::print();
cout << "Undergrad Rate: " << undergrad_rate << endl;
cout << "Year: " << year << endl;
}
//Display undergrad's current year
string get_year() {
return year;
}
//Display the undergrad's current rate
float get_rate() {
return undergrad_rate;
}
//Set a undergrad's current year
void set_year(string y) {
year = y;
}
//Display the cost for an undergrad to attend university
float tuition() const {
return 1000000;
}
};
int main() {
ifstream ip("data.txt");
if (!ip.is_open()) std::cout << "ERROR: File not found" << '/n';
string name;
string ssn;
string year;
string credit;
string gpa;
vector<Undergrad> file;
//Undergrad g(name, ssn, year, credit, gpa);
while (ip.good()) {
getline(ip, name, ',');
getline(ip, ssn, ',');
getline(ip, gpa, ',');
getline(ip, credit, ',');
getline(ip, year, '\n');
// float number = stoi(gpa);
//float number1 = stoi(credit);
Undergrad g(name, ssn, year, credit, gpa);
file.push_back(g);
}
ip.close();
Undergrad g = file.back();
file.pop_back();
file.insert(file.begin(),g);
for (int i = 0; i < file.size(); i++) {
cout << "Name: " << file[i].getName() << endl;
cout << "SSN: " << file[i].getSSN() << endl;
cout << "Year: " << file[i].get_year() << endl;
cout << "Credit: " << file[i].getCredit() << endl;
cout << "GPA " << file[i].getGPA() << endl;
cout << " " << endl;
}
system("pause");
return 0;
}
You can cast the string to a float using atof. See reference here. Be sure to include <cstdlib>. Your constructor would look like:
Student(const string n, const string s, string sGPA, string sCredits) {
name = n;
ssn = s;
gpa = (float)atof(sGPA.c_str());
credits = (float)atof(sCredits.c_str());
}
hey guys new to this site looking some help for my final project i having to create a project that takes car data saves it to the heap and has a bunch of error checking not all the way done but getting there. but i cant grasp the heap and how to input it correctly into my code here is what i have. and it has to be under 175 lines and i still have to have it ask user if they want to write to a new file or existing. thanks ahead once again question is how do i create array on the heap able to hold the number of vech specified buy user.
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
class carData4
{
public:
void setYear(int& year);
void setMake(string make);
void setModel(string);
void setMileage(int& mileage);
void setName(string name);
void setNumber(string number);
int getYear(){ return itsYear; }
string getMake(){ return itsMake; }
string getModel(){ return itsModel; }
int getMileage(){ return itsMileage; }
string getName(){ return itsName; }
string getNumber(){ return itsNumber; }
private:;
int itsYear;
string itsMake;
string itsModel;
int itsMileage;
string itsName;
string itsNumber;
};
void carData4::setYear(int & year)
{
do
{
cout << "Enter the cars Year from 1910 and 2014:\n ";
cin >> year;
itsYear = year;
if (year < 1910 || year > 2014)
cout << "INVALID! please enter a correct year! ";
} while (year < 1910 || year > 2014);
}
void carData4::setMake(string make)
{
cout << "Enter the cars make:\n\n";
cin >> make;
itsMake = make;
}
void carData4::setModel(string model)
{
cout << "Enter the cars model:\n\n";
cin >> model;
itsModel = model;
}
void carData4::setMileage(int & mileage)
{
do{
cout << "Enter the cars mileage:\n\n";
cin >> mileage;
itsMileage = mileage;
}
while (mileage <0 || mileage >10000000);
cout << "NOPE enter within 0 and million miles.\n\n";
cin >> mileage;
itsMileage = mileage;
}
void carData4::setName(string name)
{
cout << "Enter your name :";
cin >> name;
itsName = name;
}
void carData4::setNumber(string number)
{
cout << "Enter Your phone number (XXX)XXX-XXXX:";
cin >> number;
itsNumber = number;
}
int main()
{
carData4 car1;
int year, mileage, numCars, ;
string make, model, name, number;
cout << "How many vehicles are to be added to inventory?.\n\n";
cin >> numCars;
for (int i = 1; i < numCars; i++){
car1.setYear(year);
car1.setMake(make);
car1.setModel(model);
car1.setMileage(mileage);
car1.setName(name);
car1.setNumber(number);
cout << car1.getYear() << "\t" << car1.getMake() << "\t " << car1.getModel()
<< "\t" << car1.getMileage() << "\t " << car1.getName() << "\t " << car1.getNumber() << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
i add some is this correct????????????????
int main()
{
carData4 car1; // *car1=new carData4[numCars];
int year,mileage,numCars;
double *cars;
string make,model,name,number;
cout << "How many vehicles are to be added to inventory?.\n\n";
cin >>numCars;
cars = new double [numCars];
for (int i=1; i<numCars;i++){
car1.setYear(year);
car1.setMake(make);
car1.setModel(model);
car1.setMileage(mileage);
car1.setName(name);
car1.setNumber(number);
cout << car1.getYear() << "\t" << car1.getMake() << "\t " << car1.getModel()
<< "\t" << car1.getMileage() << "\t " << car1.getName() << "\t " << car1.getNumber() <<endl;
delete [] cars;
}
system("PAUSE");
return EXIT_SUCCESS;
}
The best way to have dynamic storage for your use case would be to use a vector, like so:
std::cout << "How many vehicles are to be added to inventory?.\n\n";
std::size_t n;
std::cin >> n;
std::vector<carData4> cars ( n );
//gives you:
//cars[0] ... cars[ n-1 ]
http://en.cppreference.com/w/cpp/container/vector
To dynamically allocate an array based on user input:
unsigned int array_capacity;
cout << "Enter array capacity: ";
cin >> array_capacity;
int * my_array = new int[array_capacity];
Remember to delete the array using delete [] my_array;.
Edit 1: using Car class
CarData4 * my_cars = new CarData4[numCars];
I think I am having trouble with binary file io. If I run my program, create some employee objects and then display them everything works fine. If I save the object data and reload the program I get an RTTI exception. It apears to me that my LoadEmployeeData() and Savelist(vector &e) functions work just fine. The exception occurs in my DisplayEmployeeData() function when I try to use typeid.
Just to reiterate, I am getting an RTTI error when using typeid on an object loaded from disk.
//****************header file***********
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <typeinfo>
#include <ctime>
#include <cstdlib>
using namespace std;
class Employee
{
private:
int employeeID;
char name[80];
int SSN;
public:
Employee();
Employee(int, char*,int);
virtual ~Employee();
virtual void DisplayBaseData();
//getters
int GetID();
char* getName();
int GetSSN();
//setters
void SetID(int);
void SetName(char*);
void SetSSN(int);
};//end Employee class
class Salary : public Employee
{
private:
double salary;
public:
Salary();
Salary(int, char*, int, double); //id, name, ssn, salary
~Salary();
void DisplayEmployeeData();
//getters
double GetSalary();
//setters
void SetSalary(double);
};//end class Exempt
class Hourly : public Employee
{
private:
double rate;
double hoursWorked;
public:
Hourly();
Hourly(int, char*, int, double, double); //id, name, ssn, rate
~Hourly();
void DisplayEmployeeData();
//getters
double GetRate();
double GetHoursWorked();
//setters
void SetRate(double);
void SetHoursWorked(double);
};//end Hourly Class
const int HOURLYTYPE = 0;
const int SALARYTYPE = 1;
//*******body*******
#include "lab05.h";
Employee::Employee(){};
Employee::Employee(int ID, char* nme, int ssn) : employeeID(ID), SSN(ssn)
{
strcpy(name, nme);
}
int Employee::GetID()
{
return employeeID;
}
char* Employee::getName()
{
return name;
}
int Employee::GetSSN()
{
return SSN;
}
void Employee::SetID(int i)
{
employeeID = i;
}
void Employee::SetName(char* n)
{
strcpy(name, n);
}
void Employee::SetSSN(int i)
{
SSN = i;
}
void Employee::DisplayBaseData()
{
cout << "ID: \t" << employeeID << endl;
cout << "Name: \t " << name << endl;
cout << "SSN: \t" << SSN << endl;
}
Employee::~Employee(){}
Salary::Salary(){}
Salary::Salary(int id, char* nme, int ssn, double slry) : Employee(id, nme, ssn), salary(slry){}
void Salary::DisplayEmployeeData()
{
DisplayBaseData();
cout << "Salary: \t " << salary << endl;
}
double Salary::GetSalary()
{
return salary;
}
void Salary::SetSalary(double d)
{
salary = d;
}
Salary::~Salary(){}
Hourly::Hourly(){}
Hourly::Hourly(int id, char* nme, int ssn, double rte, double worked) : Employee(id, nme, ssn), rate(rte), hoursWorked(worked){}
void Hourly::DisplayEmployeeData()
{
DisplayBaseData();
cout << "Rate: \t" << rate << endl;
cout << "Worked: \t " << hoursWorked << endl;
}
double Hourly::GetRate()
{
return rate;
}
double Hourly::GetHoursWorked()
{
return hoursWorked;
}
void Hourly::SetRate(double d)
{
rate = d;
}
void Hourly::SetHoursWorked(double d)
{
hoursWorked = d;
}
Hourly::~Hourly(){}
vector<Employee*> LoadEmployeeData()
{
vector<Employee*> employeeList;
string fileName = "";
cout << "\nEnter filename for employee data: ";
cin >> fileName;
fstream file;
file.open(fileName, ios::in, ios::binary);
char buffer[4096] = {0};
int numEntries;
file.read((char*)&numEntries, sizeof(int));
cout << numEntries << " number of entries found." << endl;
if (numEntries != 0)
{
int identifier;
for (int i = 0; i < numEntries; i++)
{
file.read((char*)&identifier, sizeof(int));
if (identifier == SALARYTYPE)
{
Employee* temp = new Salary();
file.read((char*)temp, sizeof(Salary));
employeeList.push_back(temp);
}
else if (identifier == HOURLYTYPE)
{
Employee* temp = new Hourly();
file.read((char*)temp, sizeof(Hourly));
employeeList.push_back(temp);
}
}
}
else cout << "No Entries found." << endl;
file.close();
return employeeList;
}//end LoadEmployeeData function
void ListEmployees(vector<Employee*> &e)
{
if (e.size() != 0)
{
for (int i = 0; i < e.size(); i++)
{
if (typeid(*(e[i])) == typeid(Hourly))
{
cout << "\n(" << i << ")" << endl;
dynamic_cast<Hourly*>(e[i])->DisplayEmployeeData();
}
else if (typeid(*(e[i])) == typeid(Salary))
{
cout << "\n(" << i << ")" << endl;
dynamic_cast<Salary*>(e[i])->DisplayEmployeeData();
}
}
}
else cout << "No items in list" << endl;
}// end ListEmployees function
void ModifyEmployee(vector<Employee*> &e)
{
cout << "Enter employee selection." << endl;
}
void CreateEmployee(vector<Employee*> &e)
{
bool continueLoop = true;
srand(time(0)); //seed random number generator
cout << "\n Enter new employee information." << endl;
cout << "Name: ";
char newName[80] = {0};
cin >> newName;
cout << "\n SSN: ";
int newSSN;
cin >> newSSN;
char newType = '-1';
do
{
cout << "\n Is new employee paid a (s)alary or (h)ourly rate? ";
cin >> newType;
if (newType == 's' || newType == 'h') continueLoop = false;
else cout << "incorrect input" << endl;
}while (continueLoop == true);
if (newType == 's')
{
cout << "Enter salary amount: ";
double amount;
cin >> amount;
e.push_back(new Salary(rand() % 1000 + 1, newName, newSSN, amount));
}
else if (newType == 'h')
{
cout << "Enter hourly amount: ";
double amount;
cin >> amount;
cout << "Enter hours worked: ";
double hoursWorked;
cin >> hoursWorked;
e.push_back(new Hourly(rand() % 1000 + 1, newName, newSSN, amount, hoursWorked));
}
}
void Savelist(vector<Employee*> &e)
{
if (e.size() == 0)
cout << "No employees in list. Nothing done." << endl;
else
{
cout << "Enter save filename: ";
char fileName[80] = {'\0'};
cin >> fileName;
fstream* file = new fstream();
file->open(fileName, ios::out, ios::binary);
char buffer[80] = {'\0'};
int numEntries = e.size();
file->write((char*)&numEntries, sizeof(int)); //writes number of entries
for (int i = 0; i < e.size(); i++)
{
if (typeid(*e[i]) == typeid(Salary))
{
int classType = SALARYTYPE;
file->write((char*)&classType, sizeof(int));
file->write((char*)dynamic_cast<Salary*>(e[i]), sizeof(Salary));
}
else if (typeid(*e[i]) == typeid(Hourly))
{
int classType = HOURLYTYPE;
file->write((char*)&classType, sizeof(int));
file->write((char*)dynamic_cast<Hourly*>(e[i]), sizeof(Salary));
}
}
file->close();
}
}
void DeleteEmployee(vector<Employee*> &e)
{
cout << "Input index number of employee to delete: ";
int idx = 0;
cin >> idx;
if (idx > e.size() -1)
cout << "invalid index number\n" << endl;
else
{
delete e[idx];
e.erase(e.begin() + idx); //removes from list
}
}
int main()
{
const int ZERO = 0;
const int ONE = 1;
const int TWO = 2;
const int THREE = 3;
const int FOUR = 4;
const int FIVE = 5;
const int SIX = 6;
int exitMainLoop = false; //for flow control
int mainMenuChoice = -1;
vector<Employee*> employeeList;
do
{
cout << "Select from the following options." << endl;
cout << "(1) Load employee data file." << endl;
cout << "(2) View Employees." << endl;
cout << "(3) Modify Employee data. " << endl;
cout << "(4) Create new employee." << endl;
cout << "(5) Save list to file." << endl;
cout << "(6) Delete employee data. " << endl;
cout << "(0) Exit program." << endl;
//add more options
cout << "Enter selection: ";
cin >> mainMenuChoice;
if (cin.fail())
{
cout << "\nInvalid selection. Try again" << endl;
cin.clear();
string garbage = "";
cin >> garbage;
}
else if (mainMenuChoice == ONE)
employeeList = LoadEmployeeData();
else if (mainMenuChoice == TWO)
ListEmployees(employeeList);
else if (mainMenuChoice == THREE)
ModifyEmployee(employeeList);
else if (mainMenuChoice == FOUR)
CreateEmployee(employeeList);
else if (mainMenuChoice == FIVE)
Savelist(employeeList);
else if (mainMenuChoice == SIX)
DeleteEmployee(employeeList);
else if (mainMenuChoice == ZERO)
exitMainLoop = true;
}while(exitMainLoop == false);
system("PAUSE");
}
You can't read/write raw C++ objects from/to disk if they have virtual methods (or use RTTI, which requires virtual methods) because there's no guarantee that the vtable address from the first execution will be written to disk, and there's no guarantee that the vtable will be in the same place the next time the program is run -- hence, the address that was written to disk will point somewhere incorrect when it is read back.
file->write((char*)dynamic_cast<Hourly*>(e[i]), sizeof(Salary));
looks suspicious. did you mean sizeof(Hourly)?