It's not a good idea to use
eof()
as the loop condition. It can cause a number of different issues, the first of which you discovered, the possibility of an infinite loop.
We can take a first attempt at fixing the code by changing the loop condition as follows:
1 2 3 4 5 6 7 8
|
// while array is not filled, do the following:
while (count < size)
{
getline(fin, record[count].name);
fin >> record[count].numCourses;
getline(fin, record[count].courseCode);
count++;
}
|
That should tame the never-ending looping.
But there are a few other things to be fixed too.
One, we do need to check the file status
after reading from it. Otherwise, say the rest of the file was empty and all the inputs failed, the loop would just continue regardless.
Two, when mixing
getline()
with the extraction operator
>>
there can be some problems with things getting out of synchronisation. A common solution is to use ignore() to read and discard either a single character, or everything up to the end of the current line. In particular, after the first input,
fin >> size;
the rest of the line needs to be discarded, or else the next getline will read an empty line instead of the student name.
Here's a version of the code with various changes made as summarised above:
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
using namespace std;
struct Record // struct definition
{
string name;
int numCourses;
string courseCode;
};
int main()
{
int size;
int count = 0;
ifstream fin("courses.txt");
fin >> size; // read an integer from the file, containing array size
if (!fin)
{
cout << "Could not read number of students from file\n";
return 1;
}
fin.ignore(1000, '\n'); // ignore everything until end of line
Record* record = new Record[size]; // Dynamic allocation of array
// while array is not filled AND the file status is good
// do the following:
while (count < size && fin)
{
getline(fin, record[count].name);
fin >> record[count].numCourses;
fin.ignore(); // ignore a single character
getline(fin, record[count].courseCode);
if (fin) // add 1 to count if the file access was successful
count++;
}
fin.close();
cout << "count = " << count << '\n';
for (int i=0; i<count; i++)
{
cout << "Name: " << record[i].name
<< "\nNumber of courses: " << record[i].numCourses
<< "\nCourse code: " << record[i].courseCode
<< '\n';
}
delete[] record;
return 0;
}
|