Read and Write an Array of Structs to binary file. C++ - c++

This is a header file part of a bigger project, but I am trying to save an array of structs to a binary file. When I do this (with my current code) it reads back very random information and not sure if I am close to getting it right on saving the information.
#include <fstream>
using namespace std;
class Reserv{
private:
struct ReservStruct{
int seatNum = 0;
int custID = 0;
int resvID = 0;
int resvIDcount;
};
int resvIDcount;
static int const numberOfSeats = 10;
ReservStruct Seat[numberOfSeats];
public:
/* Read and Write Files ***********************************/
void writeResvIDcount(){
ofstream IDfile("resvidcount.txt", ios::binary);
IDfile.write((char*)&resvIDcount,sizeof(resvIDcount));
IDfile.close();
}
void readResvIDcount(){
ifstream IDfile("resvidcount.txt", ios::binary);
IDfile.read((char*)&resvIDcount,sizeof(resvIDcount));
IDfile.close();
}
void writeReservations(){
ofstream resfile("reservations.txt", ios::binary);
for (int i=0; i<numberOfSeats; i++) {
resfile.write((char*)&Seat[i], sizeof(Seat));
}
}
void readReservations(){
ifstream resfile("reservations.txt", ios::binary);
for (int i=0; i<numberOfSeats; i++) {
resfile.read((char*)&Seat[i], sizeof(Seat));
}
}
/*********************************************************/
void ReserveSeat(int seatNumber, int customerID){
if (Seat[seatNumber].resvID == 0) {
Seat[seatNumber].seatNum = seatNumber;
Seat[seatNumber].custID = customerID;
Seat[seatNumber].resvID = resvIDcount;
cout << "Reservation ID: " << resvIDcount << endl;
resvIDcount = resvIDcount+1;
writeResvIDcount();
writeReservations();
}
if (Seat[seatNumber].resvID != 0) {
addToWaitingList(seatNumber, customerID);
}
}
void CancelReservation(int seatNumber){
Seat[seatNumber].seatNum = seatNumber;
Seat[seatNumber].custID = 0;
Seat[seatNumber].resvID = 0;
cout << "Reservation on seat number " << Seat[seatNumber].seatNum << " has been cancelled." << endl;
}
Reserv(){
readResvIDcount();
readReservations();
int reservchoice;
cout << "1: New Reservation\n2: Cancel Reservation\n";
cin >> reservchoice;
if (reservchoice ==1) {
int customerID;
int seatToReserve;
cout << "Enter Customer ID:";
cin >> customerID;
cout << "Seat Number:";
cin >> seatToReserve;
ReserveSeat(seatToReserve, customerID);
}
if (reservchoice==2) {
int seatNum;
cout << "Seat Number:";
cin >>seatNum;
CancelReservation(seatNum);
}
}
};

Related

Almost all forms of String comparisons are not working in C++ 11

So I am doing a school project that requires me to execute my program with arguments and display the contents of a file based on a particular action.
This is done by simply requesting the action after the file name is specified.
It is:
./executable_name 'filename' 'action'
actions include list or find. List will list all the book contents of the specific file in that order and find will find a book by it's ISBN number specified.
Now my error lies with the find function, more specifically how i compare the Strings. I cannot compare the strings within the "find" function for the life of me. Ive tried "strcmp()" with the ".c_str()", I've tried "==", I've tried "string.copmare(string2)", and nothing. I have developed some interesting clues though.
If I try to print the string from my array of arguments concatenated with a few letters it properly does some expected printing, BUT if I perform the same action from the struct instance of any particular book array it seems to be overwritten like a return carriage type.
EX:
argv[4] = 0-201-60464-7 near here
books[0].isbn = near here-60464-7
Driver File
##include"book.h"
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = argv[1];
int filesRead = read (filename, books);
if(string(argv[2])== "list")
{
for(int index =0;index < filesRead; index++ )
{
cout << books[index].title << endl;
cout << books[index].authorCount<< endl;
for(int j =0; j < books[index].authorCount; j++)
{
cout << books[index].authors[j] << endl;
}
cout << books[index].publisher <<endl;
cout << books[index].yearPublish <<endl;
cout << books[index].hardcover << endl;
cout << books[index].price << endl;
cout << books[index].isbn << endl;
cout << books[index].copies << endl;
}
}
if(argc > 3)
{
if(string(argv[2]) == "find")
{
int book_index = find(argv[3], books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j];
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
}
}
Function file
#include"book.h"
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
int read (string filename, Book books[])
{
ifstream inputFile(filename);
//validation for the file itself
if(!inputFile)
{
cout << "File does not exist!" << endl;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
string consume_line;
while(counter < 35 && getline(inputFile, books[counter].title))
{
inputFile >> books[counter].authorCount;
getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
getline(inputFile, books[counter].authors[j]);
}
getline(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
inputFile >> books[counter].hardcover;
inputFile >> books[counter].price;
getline(inputFile, consume_line);
getline(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
getline(inputFile, consume_line);
if(inputFile.eof())
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
Header File
// #file book.h
#ifndef BOOK_H
#define BOOK_H
#include <string>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
/**
* #param filename name of the input data file
* #param books[] an array of textbook records read from the file
*
* #return the number of textbook records read
*/
int read (string filename, Book books[]);
/**
* #param id the ISBN number to search for
* #param books[] the list of textbook records
* #param length the number of textbook records in the array
*
* #return the array index of the matching record, otherwise it returns -1
*/
int find (string id, Book books[], int length);
#endif /* BOOK_H */
condensed Code
e
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
int read (string filename, Book books[])
{
ifstream inputFile(filename);
//validation for the file itself
if(!inputFile)
{
cout << "File does not exist!" << endl;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
string consume_line;
while(counter < 35 && getline(inputFile, books[counter].title))
{
inputFile >> books[counter].authorCount;
getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
getline(inputFile, books[counter].authors[j]);
}
getline(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
inputFile >> books[counter].hardcover;
inputFile >> books[counter].price;
getline(inputFile, consume_line);
getline(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
getline(inputFile, consume_line);
if(inputFile.eof())
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = "test3.txt";
string isbn = "0-201-60464-7";
int filesRead = read (filename, books);
int book_index = find(isbn, books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j];
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
test file in txt or dat whichever extension preferred
#file.txt
C++ Network Programming – Volume 1
2
Douglas C. Schmidt
Stephen D. Huston
Addison-Wesley
2002
0
35.99
0-201-60464-7
236
refactored to one compilation unit and zero test files.
Fixed logic errors
added some (hopefully explanatory) comments
added handling of windows-style line endings for increased portability
Note: Avoid the use of using namespace at global scope. A reasonable exception to this rule is using namespace std::literals;
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
#include <sstream>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
void strip(std::string& str)
{
if (str.size() && str.back() == '\r')
{
str.pop_back();
}
}
std::istream& get_line_and_strip(std::istream& is, std::string& result)
{
std::getline(is, result);
strip(result);
return is;
}
// be specific about the bounds of the output variable.
int read (std::istream& inputFile, Book books[35])
{
//validation for the file itself
if(!inputFile)
{
std::cout << "File does not exist!" << std::endl;
// avoid UB by returning a value as per the function signature
return 0;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
std::string consume_line;
while(counter < 35)
{
get_line_and_strip(inputFile, books[counter].title);
inputFile >> books[counter].authorCount;
std::getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
get_line_and_strip(inputFile, books[counter].authors[j]);
}
get_line_and_strip(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
std::getline(inputFile, consume_line);
inputFile >> books[counter].hardcover;
std::getline(inputFile, consume_line);
inputFile >> books[counter].price;
std::getline(inputFile, consume_line);
get_line_and_strip(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
std::getline(inputFile, consume_line);
if(!inputFile) // tests for EOF or error during input
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[35], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
auto test_data = ""
"C++ Network Programming – Volume 1\r\n"
"2\r\n"
"Douglas C. Schmidt\r\n"
"Stephen D. Huston\r\n"
"Addison-Wesley\r\n"
"2002\r\n"
"0\r\n"
"35.99\r\n"
"0-201-60464-7\r\n"
"236\r\n"
""s;
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = "test3.txt";
string isbn = "0-201-60464-7";
auto test_file = std::istringstream(test_data);
int filesRead = read (test_file, books);
int book_index = find(isbn, books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
// would be invalid to continue if book not found
return 0;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j] <<endl;
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
Expected output:
C++ Network Programming – Volume 1
2
Douglas C. Schmidt
Stephen D. Huston
Addison-Wesley
2002
0
35.99
0-201-60464-7
236
https://coliru.stacked-crooked.com/a/9b08598ffcd0edc2

Reading file to class object

I am having trouble reading a file to my class object's members. It says it cannot read the file.
This is my class:
const int SIZE_OF = 5;
class Student
{
public:
Student();
Student(const Student &);
Student(string, int, int, int, int, int);
friend std::istream& operator >> (std::istream& in, Student& S);
void display();
private:
string lastName;
int grades[SIZE_OF];
};
The cpp file associated with my class object to define the functions:
#include "Student.h"
Student::Student()
{
int i;
string lastName = "default";
for (i = 0; i < 5; i++)
{
grades[i] = 0;
}
}
Student::Student(const Student & S)
{
int i;
lastName = S.lastName;
for (i = 0; i < 5; i++)
{
grades[i] = S.grades[i];
}
}
Student::Student(string S, int a, int b, int c, int d, int e)
{
lastName = S;
grades[0] = a;
grades[1] = b;
grades[2] = c;
grades[3] = d;
grades[4] = e;
}
std::istream& operator >> (std::istream& in, Student& S)
{
char dummy;
in >> S.lastName >> S.grades[0]
>> dummy >> S.grades[1]
>> dummy >> S.grades[2]
>> dummy >> S.grades[3]
>> dummy >> S.grades[4];
return in;
}
void Student::display()
{
int i;
int sum = 0;
double average;
cout << "Last Name: " << lastName << endl;
cout << "Grades: " << endl;
for (i = 0; i < 5; i++)
{
cout << grades[i] << endl;
}
for (i = 0; i < 5; i++)
{
sum = sum + grades[i];
}
average = sum / 5;
cout << "Average: " << average;
}
And finally, the main function that I have so far to test the file opening and reading it to the various variables inside the class.
void main()
{
fstream File;
string FileName = "ProgramSixData.txt";
bool FoundFile;
string Line;
Student testStudent;
do {
File.open(FileName, ios_base::in | ios_base::out);
FoundFile = File.is_open();
if (!FoundFile)
{
cout << "Could not open file named " << FileName << endl;
File.open(FileName, ios_base::out); // try to create it
FoundFile = File.is_open();
if (!FoundFile)
{
cout << "Could not create file named " << FileName << endl;
exit(0);
}
else;
}
else;
} while (!FoundFile);
do {
File >> testStudent;
if (File.fail())
{
cout << "Read Failed" << endl;
cout << "Bye" << endl;
exit(0);
}
else;
testStudent.display();
} while (!File.eof());
cout << "Bye" << endl;
File.close();
}
The text document that I am reading from is the following:
George
75,85,95,100,44
Peter
100,100,100,100,100
Frank
44,55,66,77,88
Alfred
99,88,77,66,55
How do I save each of the names and the associated 5 grades to a particular object of the student class?
You are digging too deep. I made an example solution for you, focusing on the parsing. Things could be way shorter and we could instantly make the students instead of doing it the map way, but I want you to understand how to parse the file, because that is obviously what you are struggling with. Ask me anything about the code if you don't understand it.
void main()
{
string FileName = "ProgramSixData.txt";
bool FoundFile;
string Line;
vector<Student> Students;
ifstream file(FileName); //an ifstream is an INPUTstream (same as a fstream with ::in flag. Passing the FileName as argument opens that file
if (file.fail()) //check if the file opened correctly
{
cout << "Failed to open inputfile\n";
return;
}
map <string, vector<int>> studentAndGrades; //map is a container that uses keys and values, every key has a value, we will use the name of the student as the key to access his marks (a vector of int)
vector<string> allLines;
string line;
while (file >> line) //these 2 linessimply reads ALL the lines to the allLines vector
allLines.push_back(line);
for (size_t i = 0; i < allLines.size(); i += 2) //loop over all lines, by 2 at a time (1 for the students name and 1 for his marks)
{
vector<int> numbers;
size_t lastCommaIdx = 0;
size_t currentCount = 0;
string scores(allLines[i + 1]); //make a copy of allLines[i + 1] for convenient use
bool firstLine = true;
for (size_t i = 0; i < scores.size(); ++i) //following code is just to split the numbers from the comma's and put them in a vector of int
{
if (scores[i] == ',')
{
if (firstLine)
{
numbers.push_back(stoi(scores.substr(lastCommaIdx, currentCount)));
firstLine = false;
}
else
{
numbers.push_back(stoi(scores.substr(lastCommaIdx + 1, currentCount)));
}
lastCommaIdx = i;
currentCount = 0;
}
else
{
++currentCount;
}
}
numbers.push_back(stoi(scores.substr(lastCommaIdx + 1))); //last number
studentAndGrades.insert(make_pair(allLines[i], numbers)); //finally, insert them in the map
}
for (const auto& student : studentAndGrades)
Students.push_back(Student(student.first, student.second[0], student.second[1], student.second[2], student.second[3], student.second[4])); //make students from the information that we read into the map
for (auto& student : Students) //display all students with a range based for loop
student.display();
file.close();
}

how to use strstr()?

i want to take data from file and store it in string array and and perform a search function with only few information like type"j" and the program able to look for data name which contain "j".
but my program cannot work.....
i am wondering am i using the strstr() correctly or not?
my text file :
Jason Derulo
5000
Martin Delux
8752
Justin Haber
51855
Alex Zander
52163
and
coding:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
//---------------------------------------------------------------------------------------------------------
typedef struct
{
char name[30],adv_srh_name[30];
double balance;
}ACCOUNT;
int main()
{
ACCOUNT record[31];
int choice,acc_amount=0;
ifstream openfile("list.txt"); //open text file
if (!openfile)
{
cout << "Error opening input file\n";
return 0;
}
else
{
ACCOUNT temp;
int i = 0;
double d = 0;
while (openfile)
{
openfile.getline(temp.name, 30, '\n');
//consume the newline still in the stream:
if ((openfile >> d).get()) { temp.balance = d; }
record[i] = temp;
i++;
}
openfile.close(); //close text file
acc_amount = i;
}
cout << "Please enter a client name:";
fflush(stdin);
cin.getline(adv_srh_name, 30);
for (int j = 0; adv_srh_name[j] != NULL; j++)
adv_srh_name[j] = toupper(adv_srh_name[j]);
cout << adv_srh_name;
for (int a = 0; a < acc_amount; a++)
{
if ((strstr(record[a].name, adv_srh_name)) != NULL)
{
cout << "Name :" << record[a].name << "\n";
cout << "Balance :" << record[a].balance << "\n\n";
}
}
return 0;
}

warning: unused variable ‘arrPixel’ [-Wunused-variable]

Main.cpp
#include <iostream>
#include <fstream>
#include "steganography.h" // call steganography class
const int arrSize = 30000;//array for contains pixels
using namespace std;
int main()
{
char FileName[20] = "new.txt";
char NewFile[20] = "new.ppm";
char arrPixel[arrSize] = {};
int count = 0;
int option;
Steganography A;//create the reference of steganopragpy class
cout<<"Choose Enocde/Decode[1/2]"; // take option from user
cin>>option;
switch(option)
{
case 1:
cout << "Enter PPM File Name" << endl;
cin>>FileName;
cout << "Enter Output File Name"<< endl;
cin>>NewFile;
A.readImage(FileName, arrPixel);//call readImage method
cout << "Encoded Successfully completed:" << endl;
A.printImage( NewFile, arrPixel);//write ppm
break;
case 2:
cout << "Enter Input File Name" << endl;
cin>>FileName;
cout << "Enter Output PPM File Name"<< endl;
cin>>NewFile;
A.readCipherText( NewFile, arrPixel);//call read file method
cout << "Decoded Successfully completed:" << endl;
A.printCipherText(FileName, arrPixel);//write ppm
break;
default:
cout<<"wrong choice";
}
// cout << NewFile << endl;
for(int ct = 0; ct > arrSize; ct++)
{
cout << arrPixel[ct];
}
return 0;
}
steganography.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "steganography.h" // call steganography class
const int arrSize = 30000;//array for contains pixels
using namespace std;
Steganography::Steganography()//call steganography constructor
{
char arrPixel[arrSize] = {};
}
void Steganography::readImage(char* FileName, char* arrPixel)//read image
{
ifstream infile (FileName);//open file
if(infile.is_open())
{
for(int count = 0; count < arrSize; count++)
{
infile >> noskipws >> arrPixel[count];
}
}
else
{
cout << "Error opening new file." << endl;
//abort();
}
infile.close();
}
void Steganography::readCipherText(char* FileName, char* arrPixel)//read text file contains ppm info
{
ifstream infile (FileName);
if(infile.is_open())
{
for(int count = 0; count < arrSize; count++)
{
infile >> noskipws >> arrPixel[count];
}
}
else
{
cout << "Error opening new file." << endl;
//abort();
}
infile.close();
}
void Steganography::printImage(char* NewFile, char* arrPixel)//write image
{
ofstream outfile (NewFile);
if(outfile.is_open())
{
int count = arrSize;
for(int i = 0; i < (count - 1); i++)
{
outfile << arrPixel[i];
}
}
else
{
cout << "Error opening new file." << endl;
// abort();
}
outfile.close();
}
void Steganography::printCipherText(char* NewFile, char* arrPixel)//write ppm file
{
ofstream outfile (NewFile);
if(outfile.is_open())
{
int count = arrSize;
for(int i = 0; i < (count - 1); i++)
{
outfile << arrPixel[i];
}
}
else
{
cout << "Error opening new file." << endl;
// abort();
}
outfile.close();
}
steganography.h
#ifndef STEGANOGRAPHY_H
#define STEGANOGRAPHY_H
#include <string>
#include <vector>
class Steganography {
private:
// Image header
std::string image_type;
int width, height;
int max_color_depth;
// Image data
std::vector<int> color_data;
// Hidden data
std::string ciphertext;
int getNthBit(char cipher_char, int n);
public:
Steganography(void); //Constructor
void readImage(char*,char*);
void printImage(char*,char*);
void readCipherText(char*,char*);
void printCipherText(char*,char*);
void cleanImage();
void encipher();
void decipher();
};
#endif
When I compile, i get this warning:
steganography.cpp: In constructor ‘Steganography::Steganography()’:
steganography.cpp:11:10: warning: unused variable ‘arrPixel’ [-Wunused-variable]
Can someone help me figuring out the problem. Also,I have to write this line const int arrSize = 30000; in both Main.cpp and steganography.cpp to avoid getting errors, is there a way to write it only on steganography.cpp without getting errors?
Here:
Steganography::Steganography()//call steganography constructor
{
char arrPixel[arrSize] = {};
}
You declare a local variable called arrPixel and you don't use it. You can remove that line.
Note that you have a warning, not an error.

c++ trouble with either RTTI or binary file io

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)?