0

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!

5
  • 2
    Too long; didn't read. I'm sorry and I don't want to be rude, but you're asking us to read far too much text for a problem that, I think, could be exposed in a couple of well constructed sentences. Please read How to Ask and minimal reproducible example. Once you've edited your question to include a short question and a minimal sample, we'll be happy to help you ;). Commented Feb 26, 2016 at 14:13
  • 1
    So what you basically want to do is: iterate over the file line by line and as long as the student id is the same, add up GPA scores? That should be doable in one loop that goes over the file contents line by line. You need a variable that holds the current student id and GPA sum. Then for a new line you compare ids, if same then sum if not output result, set sum and id to current values, rinse repeat. Commented Feb 26, 2016 at 14:15
  • YSC: I'll try to amend this so its pithier and more to the point, thanks! LiMuBei, thank you for that suggestion - unfortunately I have to calculate more than one GPA (major gpa, gpa for just comp sci classes), and I also need to make sure the GPA is weighted accordingly depending on the course hours. But I'll examine your recommendation and see if that's workable. Commented Feb 26, 2016 at 14:18
  • @LiMuBei: Make that an answer. (It is the answer). Commented Feb 26, 2016 at 14:22
  • After going back to my code I have to agree with Martin and say that I think LiMuBei totally named it. Thank you! I'm not sure how to flag your comment as the answer though. Commented Feb 26, 2016 at 17:18

1 Answer 1

1

My answer style was my attempt of following: https://meta.stackexchange.com/questions/10811/how-do-i-ask-and-answer-homework-questions

A question you have is that you do not know if you should dispense with the counter method entirely (in which case you would welcome recommendations of how best to replace it) or if your counter method is workable by placing the code for calculating GPAs more strategically.

For the former, LiMuBei mentioned the method already. When you calculate more than one GPA (major gpa, gpa for just comp sci classes), you sum up the multiple GPA's with multiple variables.

For the latter, you would like to consider the unknown elements that vary the scenarios in each of the if/while statements. (counter == 0) is the scenario for the first line. (eiD_base == eiD_temp) is the scenario for the first line and the scenario when there are at least 2 lines, the current line has the same ID as the previous line. (eiD_base != eiD_temp) is the scenario when there are at least 2 lines, the current line has a different ID as the previous line. Here're the unknown elements: {1 line, at least 2 lines}, {sameID, differentID}. When the unknown element is {1 line}, you have to modify (counter == 0) and (eiD_base == eiD_temp). In (counter == 0), you modify the code that applies to the first and the only 1 line. In (eiD_base == eiD_temp), which applies to {1 line} and {at least 2 lines}, {sameID}, the code has to work for the 2 scenarios.

For the complete solution, you are going to declare variables before the while loop, aggregate variables in (eiD_base == eiD_temp), print the GPA values of the previous ID & set the variables for the first line of a new student in (eiD_base != eiD_temp), and print the GPA values of the last ID after the while loop.

double csci_Grape_Point; // more variables for doing the calculation 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; counter++; csci_Grape_Point = 0.0; // more initialization of variables for doing the calculation } if (eiD_base == eiD_temp) { csci_Grape_Point = csci_Grape_Point + (gpa_2 * courseHours2); // more sum calculation, such as total csci credit hours } else { outputStream2 << "Previous ID: " << eiD_base << " and this is what eiD is now is now: " << eiD_temp << endl; eiD_base = eiD_2; // for the previous ID, calculate gpa for just comp sci classes // for the previous ID, calculate more gpa's // set the variable to include the first line of data of a new student csci_Grape_Point = (gpa_2 * courseHours2); // set more variables for doing the calculation } } // for the last ID, calculate gpa for just comp sci classes // for the last ID, calculate more gpa's 

Another question you have is about data calculation in (eiD_base == eiD_temp). When a line doesn't meet (eiD_base == eiD_temp), the current line is different from the previous line. You factor in GPA data from the data you aggregate in (eiD_base == eiD_temp) and the data you set for the first line of a new student in (eiD_base != eiD_temp).

You probably want to solve a simpler problem first, with a file with 1 line and 2 lines, if the problem is not easily solved for you and you would like to attempt to do well in programming.

Sign up to request clarification or add additional context in comments.

1 Comment

This was a superb synthesis of everything I read earlier, with additional insights. Thank you so much for this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.