Storing objects (read from file) into vectors

So for my comsci assignment, I need to read in this text file with a butt load of messages. Here is what the text file looks like:


1 R
Jemma
Harry
What were you thinking?
Harry,

You seriously need to stop claiming your paperclip orders under
the heading art supplies.

Jemma
EOF
2 R
Jemma
Jason
I really really want to talk to you about those expense claims!
Subject says it all...

Jemma
EOF



The first char is the message number, second is a status char meaning if it's read or unread, 2nd line is sender, 3rd line is recipient, 4th line is subject, and 5th line onward until "EOF" is the message body.

Now I've been able to read in all the lines perfectly into separate variables, with getline() and fstream, but now I figured I could store these messages as objects inside a vector if I create a class. This is my test code, everything compiles, except when I run it, it ends up storing the first message twice, instead of continuing the getline() from where it stopped before. Not sure how to get rid of this.

Here's my code:


#include <iostream>

#include <fstream>
#include <string>
#include <vector>

using namespace std;

// this is the class that I want to use to create instances of the messages
class Message
{
public:
Message(); // default constructor
void printMessage() const; // this prints it out so I can see if it works

private:
int messageNum;
string status;
string sender;
string recipient;
string subject;
string messageBody;

};

Message::Message() // default constructor
{
ifstream fin; // declares fin to ifstream
fin.open("mail.txt"); // opens the text file

fin >> messageNum; // takes in the first char for message number
getline(fin, status); // takes in status R for read or N for new
getline(fin, sender); // sender
getline(fin, recipient); // recipient
getline(fin, subject); // subject




while (message != "EOF") // this will read in the message body until it sees EOF which means it is end of message body
{
messageBody.append(message); // puts the various lines in message body together
if (messageBody != "")
{
messageBody.append("\n"); // adds the hard returns
}
getline(fin, message); // gets the next line
}


}

void Message::printMessage() const // this member function just prints out all the info collected
{
cout << messageNum << " " << status << endl << sender << endl << recipient << endl << subject << endl << messageBody;
}

int main()
{
Message abc; // creates instance
Message cde; // another instance


vector<Message> systemMessages; // creates vector
systemMessages.push_back(abc); // appends first instance
systemMessages.push_back(cde); // appends second instance
systemMessages[0].printMessage(); // calls member function
systemMessages[1].printMessage(); // calls member function for other
}


My output ends up being the first message twice, so obviously fin is restarting at the beginning instead of where it left off. Does anyone know how I can fix this? Thanks :D
This is because you are closing and reopening the file every time you read. The ctor is called for every object you create, and if you open the file in the ctor, it's being reopened for evey object.

You need to broaden the scope of the file. Move it into main, and pass the istream to your Message ctor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Message
{
public:
  Message(istream& fin)
  {
    // use the passed 'fin' here instead of opening the file
    // ...
  }
  //...
};

int main()
{
  ifstream fin;
  fin.open("mail.txt");

  // instead of calling the default ctor, call the one that takes an ifstream,
  //  and give it our 'fin' ifstream:
  Message abc(fin);
  Message cde(fin);

  // because 'fin' wasn't reopened, 'cde' will pick up where 'abc' left off in the file

  //...
}
Thanks for the help! Yeah I knew it had to do with the scope, wasn't sure if I could pass it into the class, I tried declaring fin as a global, but that didn't work. Anyways, that worked great!

Thank you, kind sir.
Topic archived. No new replies allowed.