开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜