I/O overloading and reading from text files
I need to define a read and a print function for a class that has an array of objects as a private variable. I have to read in objects from a text file and print them to the screen. To do this I need to overload the << and >> operators. I understand I need to use loops to read and print the information stored in the array but I'm not sure how to accomplish this. My lecturer has given us a skeleton code which is basically function prototypes and the main function which I need to stick to. I understand how this works with public structs as I have done this exact scenario using that but the private variables of class' are tripping me up.
class EmployeeList {
public:
//Constructors
E开发者_JS百科mployeeList();
EmployeeList(istream&);
//Accessors
bool isEmpty() const;
bool isFull() const;
int size() const; //Number of employees in list
Employee item(int i) const; //i'th employee
//Mutators
void setItem(int i,const Employee& e);
//I/O functions, sets the i'th emplyee to e
void read(istream&);
void print(ostream&) const;
private:
enum {MAXSIZE = 100};
Employee list[MAXSIZE];
int count; //Number of employees in the current list
};
EmployeeList::EmployeeList() {
count = 0;
}
EmployeeList::EmployeeList(istream& in) {
//list[MAXSIZE] = in;
}
bool EmployeeList::isEmpty() const {
return (count == 0);
}
bool EmployeeList::isFull() const {
return (count == MAXSIZE);
}
int EmployeeList::size() const {
return count;
}
Employee EmployeeList::item(int i) const {
}
void EmployeeList::setItem(int i, const Employee& e) {
}
void EmployeeList::read(istream& in) {
Employee tempList;
while (in >> tempList) {
}
}
void EmployeeList::print(ostream& out) const {
for (int i=0; i < size(); i++) {
}
cout << out;
}
The above part is the Class EmployeeList while the below part are overloading functions. The commented out parts are ideas that I thought might work but didn't.
istream& operator>>(istream& in, EmployeeList& l) {
l.read(in);
return in;
}
ostream& operator<<(ostream& out, const EmployeeList& l) {
l.print(out);
return out;
}
Below is the main function given to us.
int main() {
authorInfo();
ifstream infile("a1in.txt");
if(!infile) {
cout << "file 'alin.txt' not found.";
return EXIT_FAILURE;
}
EmployeeList theList(infile);
cout << endl;
cout << theList.size() << " employees read:\n" << theList << endl;
process(theList);
return EXIT_SUCCESS;
}
Hope someone can steer me in the right direction! Let me know if you need more of the code. Thanks!
EDIT: Employee read and print functions:
void Employee::read(istream& in) {
in >> name >> id >> salary;
}
void Employee::print(ostream& out) const {
out << getName() <<" "<< getID() <<" "<< getSalary() << endl;
}
Employee overloading:
istream& operator>>(istream& in, Employee& e) {
e.read(in);
return in;
}
ostream& operator<<(ostream& out, const Employee& e) {
e.print(out);
return out;
}
EDIT 2: Updated read() function. The line with the while is where the error is.
void EmployeeList::read(istream& in) {
Employee inEmployee;
while (in >> inEmployee && count < MAXSIZE) {
list[count] = inEmployee;
count++;
}
}
EDIT 3: Here is the print() function I have so far. It does indeed print but I get the default constructor information rather than information from the file. Is this a read or print function issue? I'm thinking read function still.
void EmployeeList::print(ostream& out) const {
cout << endl;
for (int i=0; i < count; i++) {
out << list[count];
}
}
Array Bounds
In your class, you have:
Employee list[MAXSIZE];
Given this, there is an error the code you tried:
EmployeeList::EmployeeList(istream& in) {
list[MAXSIZE] = in;
}
list
only has elements from list[0]
to list[MAXSIZE - 1]
. list[MAXSIZE]
is one past the end of the array, and is invalid.
Constructors
That said, I'd strongly recommend against having a constructor that takes an istream&
. It is far better to construct an empty object with the default constructor, then use its read(istream&)
method (via operator <<
) to load the data. In other words, rather than:
EmployeeList theList(infile);
use:
EmployeeList theList;
infile >> theList;
If you're required to have a constructor that takes an istream&
, just have it call read()
after initializing the object:
EmployeeList::EmployeeList(istream& in): count(0) {
read(in);
}
Note that only one constructor is called, so the initialization in EmployeeList::EmployeeList()
does not happen in EmployeeList::EmployeeList(istream&)
. I hear the new version of C++ deals with this unnecessary repetition, but for the time being that's where we are.
Naming
Another thing: your code will be less confusing with better variable names. In this case:
void EmployeeList::read(istream& in) {
Employee tempList;
while (in >> tempList) {
}
}
Don't say tempList
because it's not a "temporary list", it's a single Employee
that has been read. Better would be:
void EmployeeList::read(istream& in) {
Employee inEmployee;
while (in >> inEmployee) {
list[count++] = inEmployee;
}
}
This looks like a homework so i'll try to just give you a hint:
void EmployeeList::read(istream& in) {
Employee tempList;
while (in >> tempList) {
//here you are creating a tempList so after you fill in the values in tempList
//the tempList is to become a part of Employee list[MAXSIZE];
}
}
and how do you fill in the values? You do this using your constructor and maintaining the count
EmployeeList::EmployeeList(istream& in) {
//here...
}
You could start off by figuring out how to read in input. The approach, which is likely incomplete, that I would take is this:
EmployeeList::EmployeeList(istream& in) {
count = 0;
read(in); // delegate it to avoid duplication
}
void EmployeeList::read(istream& in) {
Employee tempList;
while (in >> tempList && count < MAXSIZE) {
list[count] = tempList;
++count;
}
}
You will need to overload operator>>
for Employee
class for this to work.
Here is how I would write this, without the skeleton constraint. Feel free to adapt to your assignment requirements.
Source: http://www.ideone.com/R9EeF
Iostreams are hard to master. You have to read about std::getline
, the std::ios
flags and stringstreams to understand how to parse an employee list with them.
I prefer giving you a working template (that you cannot use for your assignment since I don't make use of the skeleton at all), since there is a lot to say about iostreams.
Also feel free to ask questions, so that I can enhance my answer with your actual problems.
精彩评论