I’m in a CS101 class at my school using C++. I have a program that has to read a file in this format:
Ramirez, Manny
1572838992 a 4 b 5 x 4 a 7 c 3 c 4 *
Kemp, Matt
3337474858 a 4 b 4 b 4 a 4 *
It is supposed to read the file, calculate the GPA of each student and output the student’s name, ID, units, and GPA. I have been trying different things for a while now, and I’ve been going back and forth with infinite loops. I got help from a friend, who had me include some stuff.
I have tried changing the condition of the loop inside the while (!eof) loop so many times I can’t count them all. Every time I look up what to do online, the advice I get is just to not use while !eof because it has a propensity to cause infinite loops. Well, I know that now, but my professor wants us to do it that way.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <sstream>
using namespace std;
int main() {
char grade;
int units=0, studentsGrade=0, studentUnits=0;
int unitTotal=0;
float gradeTotal=0, gpa = 0;
string inputName, outputName, fullName;
long ID;
ifstream inputFile;
ofstream outputFile;
cout << "Please enter the input filename: ";
cin >> inputName;
cout << "Please enter the output filename: ";
cin >> outputName;
inputFile.open(inputName.c_str());
if (inputFile.fail())
cout << "Bad input file name." << endl;
else {
outputFile.open(outputName.c_str());
outputFile << left << setw(25) << "Name" << setw(15) << "ID" << setw(15)
<< "Units" << setw(15) << "GPA" << endl;
outputFile << "--------------------------------------------------------------------------------" << endl;
cout << left << setw(25) << "Name" << setw(15) << "ID" << setw(15)
<< "Units" << setw(15) << "GPA" << endl;
cout << "--------------------------------------------------------------------------------" << endl;
getline(inputFile, fullName);
while (!inputFile.eof()) {
gpa = 0;
unitTotal = 0;
gradeTotal = 0;
inputFile >> ID;
outputFile << setw(25) << fullName;
outputFile << setw(15) << ID;
cout << setw(25) << fullName << setw(15) << ID;
string line;
getline(inputFile,line);
istringstream iss(line);
while (!iss.eof()) {
units = 0;
iss >> grade >> units;
if (grade == '*')
break;
if (units > 0 && units <=5 && (grade == 'a' || grade == 'A')) {
gradeTotal += 4 * units;
studentsGrade += 4 * units;
unitTotal += units;
studentUnits += units;}
else if (units > 0 && units <=5 && (grade == 'b' || grade == 'B')) {
gradeTotal += 3 * units;
studentsGrade += 3 * units;
unitTotal += units;
studentUnits += units; }
else if (units > 0 && units <=5 && (grade == 'c' || grade == 'C')) {
gradeTotal += 2 * units;
studentsGrade += 2 * units;
unitTotal += units;
studentUnits += units; }
else if (units > 0 && units <=5 && (grade == 'd' || grade == 'D')) {
gradeTotal += 1 * units;
studentsGrade += 1 * units;
unitTotal += units;
studentUnits += units; }
else if (units > 0 && units <=5 && (grade == 'f' || grade == 'F')) {
unitTotal += units;
studentUnits += units; }
else if (grade == '*') {
unitTotal += 0;}
else {
unitTotal += 0; }
}
gpa = (float)gradeTotal / unitTotal;
outputFile << fixed << showpoint;
outputFile << setw(15) << unitTotal << setw(15) << setprecision(2) << gpa << endl;
cout << fixed << showpoint;
cout << setw(15) << unitTotal << setw(15) << setprecision(2) << gpa << endl;
getline(inputFile,fullName);
}
outputFile << "The GPA for all students is " << setprecision(2) << (float)studentsGrade / studentUnits;
cout << "The GPA for all students is " << setprecision(2) << (float)studentsGrade / studentUnits << endl;
}
inputFile.close();
outputFile.close();
cout << endl;
return 0;
}
If anyone can explain to me why I keep getting an infinite loop, I would really appreciate it.
Though it needs to be verified by running the code, it seems like you are getting either
failbitorbadbitset but not theeof. This may happen, for example, after you do other reads and notgetline()– for exampleinputFile >> ID;.Since you are only checking for the
eof, the loop runs endlessly and I/O errors are getting ignored. I’d say try using the result ofgetline()and useoperator void*of thestd::istreaminstead of checkingeof().If your professor wants you to use
eof()only, then try to workaround error checking. The solution could be to use special values and assume that if read operation didn’t set the value to something else then it has failed, and break out of the loop. For example, setIDtoLONG_MAXbefore read, and make sure it is notLONG_MAXafter.And after all – just run the code under debugger on a small working data set, step through and see what happens. Get yourself familiar with a debugger, and practice troubleshooting skills. That will for sure save you a lot of time throughout your career.
See also – http://www.cplusplus.com/reference/iostream/ifstream/
Good luck!