Lets go thought this bit by bit
int main()
{
std::stringstream stream;
stream
's not used here. For now let's get rid of it. It'll come back again later, though.
std::string current;
Student temp;
Student *database = new Student[50];
This creates 50 Student
s.
inFile.open("students.dat", std::ifstream::in);
outFile.open("FullReport.txt",std::ofstream::out);
Opens the files. Can be done a bit better, but right.
while(getline(inFile,current))
{
Perfect. Got a line from the file.
for(int i = 0; i < 50; i++)
With this one line from the file, do the same thing 50 times. Ask your Rubber duck if it thinks this makes sense.
{
Student[i] = new Student(current);
Student
is a type, not a variable. You can't store in a type. Odds are you meant to use database
, but it is an array of Student
s, and new Student(current)
provides pointers to Student
s.
outFile << Student[i] <<std::endl;
}
inFile.close();
outFile.close();
Closing the files too soon. You haven't read all of the students yet.
}
}
How to fix:
int main()
{
std::string current;
Student **database = new Student*[50];
database
is an array of 50 pointers to Student
s, al ready to accept new Student
s. But more on this later.
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
If we define the file streams here and specify the direction (ifstream
, ofstream
) we don't need to specify it again. Plus we can open the file right in the constructor. Who needs messy calls to open
? Finally because the files are local variables they will automatically be destroyed and close at the end of the function. No need for a messy call to close
. (See What is meant by Resource Acquisition is Initialization (RAII)? for more on this concept) Code you don't have to write doesn't have bugs. And if it somehow does, they aren't your fault.
int count = 0;
count
is a much more descriptive name than i
while (std::getline(inFile, current))
{
nothing changed here. This is fantastic. There is a famous question on Stack Overflow that is famous because of how many people get this wrong. Kudos. You got it right.
database[count] = new Student(current);
new Student
allocated and added to database. More on this later.
outFile << *database[count] << std::endl;
And written to output file. Note the *
to dereference the pointer and get the value pointed at so it can be printed with a regular <<
operator (which you have to provide, by the way). Without the *
the program will print out the contents of the pointer: An address.
count++;
}
}
And one more time without all of the explanation for easy code reading
int main()
{
std::string current;
Student **database = new Student*[50];
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
int count = 0;
while (std::getline(inFile, current))
{
database[count] = new Student(current);
outFile << *database[count] << std::endl;
count++;
}
}
OK it's later. You don't want
Student **database = new Student*[50];
It's pretty gross for several reasons.
- Modern computers are fantastic at thinking in straight lines. If the data is on one nice straight line they can read ahead and have the data ready for you before you need it. Arrays of data are awesome. Arrays of pointer to data prevent the computer from getting up speed. It reads one
Student
, then it has to look up another pointer to find the next Student
. This can be slow. Cripplingly slow. With an array of Student
s while you are using Student
0, the computer is loading (or has already loaded when it loaded Student
0) the next bunch of Student
s.
- Every dynamic allocation has a cost. The program has to ask the OS for a block of memory. The OS has to find one. This can be expensive. It's much better to get one big block of memory and divvy it up into an array of
Student
s.
- Each dynamic allocation has to be put away. Allocate 50
Student
s and you need to have code that puts away 50 Student
s. Allocate an Array of Student
s, you put away one Array of Students
You want something more like
int main()
{
std::string current;
Student *database = new Student[50];
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
int count = 0;
while (std::getline(inFile, current))
{
database[count] = Student(current);
outFile << *database[count] << std::endl;
count++;
}
}
And of course what you really want is
int main()
{
std::string current;
std::vector<Student> database;
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
while (std::getline(inFile, current))
{
database.emplace_back(current);
outFile << database.back() << std::endl;
count++;
}
}
But this will get a nice round zero from the instructor. First rule of school is give the teacher what they want and pass the course. Second rule is read a bunch of other stuff to learn what you weren't taught so you won't be useless once you graduate.