I’m currently working on a project for my intro CS class. We are still pretty new to C++ and working with rudimentary concepts like while and for loops as well as file streams. The below problem is supposed to be resolved without resort to advanced features like arrays, vectors or functions.
Basically, I take a text file (FILE ONE) that has student and course data and create a new file. File one (where I’m inputting the data from) has 6k lines. Here’s an example below:
20424297 1139 CSCI 16000 W -1 3.00 RNL 20424297 1142 PSYCH 18000 W -1 3.00 RLA 20424297 1142 PSYCH 22000 W -1 3.00 RLA 20608974 1082 ENGL 12000 A- 3.7 3.00 RECR 20608974 1082 HIST 15200 B+ 3.3 3.00 FUSR 20608974 1082 PHILO 10100 A+ 4 3.00 FISR See that very first column? Each unique set of numbers represents a student (also known as an eiD). File one is a giant list of every class a student took, and includes the subject, courses and grades they got.
The point of this project is to create a new text file that summarizes the GPAs of each student. That part I’m fairly confident I could figure out (taking cumulative GPA data). What confuses me is how I’m supposed to compare lines within the file to one another.
My professor did make things easy by having all the data grouped together by student. That lightens my load a little bit. I basically have to go through this file, line by line, and compare it with the next line to see if it has the same student ID number.
My first inclination was to create a series of nested while loops. The first loop would be active as long as data was being read. My next inclination was to repeat this in another loop. I would then create variables to hold the previous line’s student ID number and the current lines student ID number, creating conditions that would be active depending on whether or not they were the same or not:
while (sdStream2 >> eiD_2 >> semester_2 >> subject_2 >> coursenumSD_2 >> grade_2 >> gpa_2 >> courseHours2 >> code_2) // This loop will keep running until there's no data left { string eiD_base = eiD_2; // eiD_base was the variable I made to hold the "previous" student's ID, for comparison to the next line while (sdStream2 >> eiD_2 >> semester_2 >> subject_2 >> coursenumSD_2 >> grade_2 >> gpa_2 >> courseHours2 >> code_2) // This loop unfortunately reads the entire file, defeating its intent { string eiD_temp = eiD_2; // eiD_temp was the variable I made to hold the current student ID, for comparison if (eiD_base == eiD_temp) { outputStream2 << "Same line :( " << endl; } else { outputStream2 << eiD_2 << endl; // this is where you post the student data from the previous line! } } } After compiling and running the above, I came to the realization that this approach would not work because the second, nested loop, would run through every line in the FILE ONE without touching the first loop. I eventually figured out another method that used a counter instead:
// NOTE: The logic of the below code is as follows: // Create a counter to note what the first student ID is. // Store that value in eiD_Base when counter = 0. Increment counter. // Now change eiD_Base everytime you find a line where eiD_temp // differs from eiD_base. string eiD_base; string eiD_temp; int counter = 0; // counter to help figure out what the first student ID was while (sdStream2 >> eiD_2 >> semester_2 >> subject_2 >> coursenumSD_2 >> grade_2 >> gpa_2 >> courseHours2 >> code_2) { eiD_temp = eiD_2; if (counter == 0) { eiD_base = eiD_2; // basically, set the first student ID to eiD_base when counter is 0. This counter is incremented only once. counter++; } if (eiD_base == eiD_temp) { outputStream2 << "Same ID: " << eiD_2 << endl; // NOTE: This is my first instinct as to where the code for calculating GPAs should go. // The problem is that if that if the code is here, how do I factor in GPA data // from a line that doesn't meet (eiD_base == eiD_temp)? I feel like that data would // be jettisoned from calculations. } else { outputStream2 << "Previous ID: " << eiD_base << " and this is what eiD is now is now: " << eiD_temp << endl; // This is my first instict for eiD_base = eiD_2; // if eiD_base !== eiD_temp, have eiD_base reset here. } } That seemed closer to what I needed. However, I noticed another issue. With this method, when the variables I created to note changes in student id (eiD_base & eiD_temp) are not equal on a line of data, it seems like that line is jettisoned. Given that I need to calculate a number of things like GPA data for each student, having a method that doesn’t allow to accumulate data for the first line of a different student isn’t a good solution.
I don't know if I should dispense with the counter method entirely (in which case I would welcome recommendations of how best to replace it) or if my counter method is workable by placing the code for calculating GPAs more strategically. Any insight or help would be most welcome!