### why this loop?

I have a project I'm working on that's got several parts to it. I'm only including the first parts on this post (for now). It involves reading a file of 30 student ID's and numerical test scores, getting the average and calculating the letter grade. I can't figure out why it's crashing. Any insight would be great. Thanks in advance!

Sample input text File:
1000 Mufutau Gibson 2
1001 Taylor Duke 7
1002 Cathleen Norris 4
1003 Alexis Hodges 6
1004 Harper Kinney 5
1005 Calista Reeves 1
1006 Reece Barrera 2
1007 Jessica Reyes 7
1008 Nelle Berry -1
1009 Alexis Mcdonald 1
1010 Piper Everett 5
1011 Amelia Clay 8
1012 Quamar Gonzales 4
1013 Cheryl Hall 9
1014 Shafira Reynolds 3
1015 Haviva Turner 0
1016 Lani Park 1
1017 Theodore Coffey 10
1018 Marny Stuart -1
1019 Noelani Stuart 6
1020 Upton Nicholson 9
1021 Jason Paul -1
1022 Dominic Jensen 4
1023 Paul Nielsen 8
1024 Marvin Lamb 5
1025 Anika Todd 4
1026 Colton Jennings 1
1027 Igor Hammond 3
1028 Haviva Austin 1
1029 Ignatius Potts 0

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104`` ``````#include #include #include #include #include #include using namespace std; void insertionSort_byInteger(int arrtosort[], int size); void insertionSort_ByString(string arrtosort[], int size); const int MAXSTUDENTS = 30; // we will assume our files are always 30 lines //const char FILENAME[40] = "grades.txt"; const char FILENAME[40] = "TestScores2.txt"; int main() { string fname[MAXSTUDENTS]; // string variable for first name string lname[MAXSTUDENTS]; // string variable for last name ifstream inFile; int id, idx, score, avg, s = 0, numofstudents = 0, totalgrade = 0; int num, target, ids[idx], scores[idx], p = 0, percent; string grade, firstName, lastName, grades[idx], targetGrade, targetLetter; inFile.open(FILENAME); //read file and get average while (s <= MAXSTUDENTS) { inFile >> id; inFile >> firstName; inFile >> lastName; inFile >> score; if (score >= 0 && score <= 10) { totalgrade = totalgrade + score; numofstudents++; } s = s + 1; cout << id << firstName << lastName << score << endl; } avg = totalgrade/numofstudents; inFile.close(); //read file, generate letter grade and create new file ifstream inFile2; ofstream outFile1; inFile2.open(FILENAME); outFile1.open("TestScores_Grades2.txt"); for(idx = 0; idx < s; idx++) { inFile2 >> id >> firstName >> lastName >> score; if (score == avg || score == avg +1) grade = "B"; else if (score == avg + 2 || score == avg + 3) grade = "A-"; else if (score == avg +4 || score == 10 ) grade = "A"; else if (score == avg - 1) grade = "C"; else if (score >= 0 && score <= (avg - 2)) grade = "F"; outFile1 << id << " " << firstName << " " << lastName << " " << score << " " << grade << endl; } inFile2.close(); system("PAUSE"); return EXIT_SUCCESS; } void insertionSort_byInteger(int arrtosort[], int size) { int temp = arrtosort[0]; for(int i = 1; i <= size; i++) { temp = arrtosort[i]; int j = 0; for(j = i; j > 0; j--) if(temp < arrtosort[j - 1]) arrtosort[j] = arrtosort[j - 1]; else break; arrtosort[j] = temp; } } void insertionSort_ByString(string arrtosort[], int size) { string temp = arrtosort[0]; for ( int i = 1; i <= size; i++ ) { temp = arrtosort[i]; int j = 0; for ( j = i; j > 0; j--) if ( temp < arrtosort[j - 1]) arrtosort[j] = arrtosort[j - 1]; else break; arrtosort[j] = temp; } }``````
 ``12`` `````` int id, idx, score, avg, s = 0, numofstudents = 0, totalgrade = 0; int num, target, ids[idx], scores[idx], p = 0, percent;``````

I highlighted potential problems. First, ids and scores should be declared as an array with a size of 30. C++ requires it be a constant value (obviously you're compiler is letting you slide (if you turned on extra warnings or strict C++, you would have likely caught that mistake)). Next, even though you shouldn't be able to create arrays like this, let's assume you're allowed to. idx isn't initialized to anything so for all we know it could be 0, 10,000, or -435. -435 is bad since you can't allocate negative memory (if you don't understand that, just understand arrays need to be an int > 0). You can have an array of size 0, but I believe it just points to NULL then (not positive, never tried/tested it). As soon as you go to write to those arrays, assuming the value of idx wasn't a valid value to declare an array size, your program will crash.

Fix that and see where that gets you.
ok thanks! Let me try to fix these and see what happens.
Not sure but I will say that by line 46, s = 31. Also, avg is being calculated with integral division.
on line 30 you read 31 lines due to the `<=`

if `inFile` cannot be opened it is likely that `numofstudents` remains 0 and that will cause a crash
Looking through your code, your arrays aren't ever used. You don't store the information from the file in them, and you don't even use them for calculations. I don't see the purpose of them in your code (however, it's more beneficial for you to use them than not). Also, this logic `//read file and get average ` and this `//read file, generate letter grade and create new file ` are illogical. File streams take up a decent chunk of processing power (negligible in this example, but nonetheless better to avoid constant read/writes unless necessary) so it's best to open and read once, close, then play with the information.

As moorecm said, you need to do at least float division if you want something other than a whole number back as your average. Your best bet is to do a type cast since neither of the variables in the division are floating types.

I'm hoping you plan on actually using your functions, because they aren't being used in your code (from what I can see) and seem like a waste of decent code if not. I didn't thoroughly look over them, but they don't look wrong, they just don't look good, to me anyways. It looks like a simple bubble sort. Only thing that might cause you an issue is the `else break;` line.
Here's what I got so far. I was able to get it to run. I have MAXSTUDENTS as a constant to 30 which I assign as the size indicator to all the arrays. Is that ok? I added a couple of cout statements to verify, but I'll have to remove them when the whole project is complete. My compiler is allowing this to run and I got the results I needed, but I want to write it correctly. idx is declared and then initialized to 0 in the for loop. If this is ok, then I will jump to the next portion involving searching and sorting through the file.

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109`` ``````#include #include #include #include #include #include using namespace std; void insertionSort_byInteger(int arrtosort[], int size); void insertionSort_ByString(string arrtosort[], int size); const int MAXSTUDENTS = 30; //assume our files are always 30 lines //const char FILENAME[40] = "grades.txt"; const char FILENAME[40] = "TestScores2.txt"; int main() { string fname[MAXSTUDENTS]; string lname[MAXSTUDENTS]; string grades[MAXSTUDENTS]; int ids[MAXSTUDENTS], scores[MAXSTUDENTS]; ifstream inFile; int id, idx, score, avg, s = 0, numofstudents = 0, totalgrade = 0; int num, target, p = 0, percent; string grade, firstName, lastName, targetGrade, targetLetter; inFile.open(FILENAME); //read file and get average while (s < MAXSTUDENTS) { inFile >> id; inFile >> firstName; inFile >> lastName; inFile >> score; if (score >= 0 && score <= 10) { totalgrade = totalgrade + score; numofstudents++; } s = s + 1; //cout << id << firstName << lastName << score << endl; } avg = totalgrade/numofstudents; cout << "The average score is: " << avg << endl << endl; inFile.close(); //read file, generate letter grade and create new file ifstream inFile2; ofstream outFile1; inFile2.open(FILENAME); outFile1.open("TestScores_Grades2.txt"); for(idx = 0; idx < MAXSTUDENTS; idx++) { inFile2 >> id >> firstName >> lastName >> score; if (score == avg || score == avg +1) grade = "B"; else if (score == avg + 2 || score == avg + 3) grade = "A-"; else if (score >= avg +4 || score == 10 ) grade = "A"; else if (score == avg - 1) grade = "C"; else if (score >= 0 && score <= (avg - 2)) grade = "F"; else if (score < 0) grade = " "; outFile1 << id << " " << firstName << " " << lastName << " " << score << " " << grade << endl; cout << id << " " << firstName << " " << lastName << " " << score << " " << grade << endl; } inFile2.close(); system("PAUSE"); return EXIT_SUCCESS; } void insertionSort_byInteger(int arrtosort[], int size) { int temp = arrtosort[0]; for(int i = 1; i <= size; i++) { temp = arrtosort[i]; int j = 0; for(j = i; j > 0; j--) if(temp < arrtosort[j - 1]) arrtosort[j] = arrtosort[j - 1]; else break; arrtosort[j] = temp; } } void insertionSort_ByString(string arrtosort[], int size) { string temp = arrtosort[0]; for ( int i = 1; i <= size; i++ ) { temp = arrtosort[i]; int j = 0; for ( j = i; j > 0; j--) if ( temp < arrtosort[j - 1]) arrtosort[j] = arrtosort[j - 1]; else break; arrtosort[j] = temp; } }``````
Oops I'm just seeing a couple of your other replies guys. Let me look through this again.
By the way, the arrays are being used further down in the program which I haven't included here yet. I was just tackling each step one by one for now.
 My compiler is allowing this to run and I got the results I needed, but I want to write it correctly.

I hope the result that you got was 3.76666... Use a calculator on the 30 numbers and see for yourself.

You'll want to do the division using doubles:

 ``12345`` ``````double count = 30; double total; // populate total // ... double avg = total/count;``````

 As moorecm said, you need to do at least float division if you want something other than a whole number back as your average. Your best bet is to do a type cast since neither of the variables in the division are floating types.

Casting is another option but I strongly recommended avoiding casts whenever possible. In this case, I'd just change the type.
Last edited on
PART 1:
I'm splitting my program in 2 posts cause it won't let me paste it in one. It's ok that the average is a whole number. I don't necessarily need to type cast it. I finally got the file to save correctly to the arrays, but now I need to run the menu. Starting with #1 - a sort function. I'm new to sort. I was given this insertionSort template to use. I tried to run #1, but although it looks like the ID's get sorted, the other columns print out garbage. what am I missing?

 ``1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495`` ``````#include #include #include #include #include #include using namespace std; void insertionSort_byInteger(int arrtosort[], int size); void insertionSort_ByString(string arrtosort[], int size); const int MAXSTUDENTS = 30; const char FILENAME[40] = "TestScores2.txt"; const char NEWFILENAME[40] = "TestScores_Grades2.txt"; int main() { string fname[MAXSTUDENTS]; string lname[MAXSTUDENTS]; string grades[MAXSTUDENTS]; int ids[MAXSTUDENTS], scores[MAXSTUDENTS]; ifstream inFile; int id, idx, score, s = 0, avg, totalgrade = 0, numofstudents = 0; int num, target, p = 0, percent; string grade, firstName, lastName, targetGrade, targetLetter; inFile.open(FILENAME); //read file and get average while (s < MAXSTUDENTS) { inFile >> id; inFile >> firstName; inFile >> lastName; inFile >> score; if (score >= 0 && score <= 10) { totalgrade = totalgrade + score; numofstudents++; } s = s + 1; //cout << id << firstName << lastName << score << endl; } avg = totalgrade/numofstudents; //cout << "The average score is: " << avg << endl << endl; //inFile.close(); inFile.clear(); inFile.seekg(0); //read file, generate letter grade and create new file //ifstream inFile2; ofstream outFile1; //inFile2.open(FILENAME); outFile1.open(NEWFILENAME); for(idx = 0; idx < MAXSTUDENTS; idx++) { inFile >> id >> firstName >> lastName >> score; if ( score != -1 ) { if (score == avg || score == avg +1) grade = "B"; else if (score == avg + 2 || score == avg + 3) grade = "A-"; else if (score >= avg +4 || score == 10 ) grade = "A"; else if (score == avg - 1) grade = "C"; else if (score >= 0 && score <= (avg - 2)) grade = "F"; outFile1 << id << " " << firstName << " " << lastName << " " << score << " " << grade << endl; } else outFile1 << id << " " << firstName << " " << lastName << " " << score << endl; } inFile.close(); //read letter grade file and launch menu ifstream inFile2; inFile2.open(NEWFILENAME); idx = 0; while (idx < MAXSTUDENTS) { inFile2 >> ids[idx] >> fname[idx] >> lname[idx] >> scores[idx] ; if ( scores[idx] != -1 ) inFile2 >> grades[idx]; cout << ids[idx] << fname[idx] << lname[idx] << scores[idx] << grades[idx] << endl; idx++; } inFile2.close();``````

PART 2:

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144`` `````` do { cout << setw(30) << "QUIZ RESULTS MENU " << endl; cout << setw(30) << "***************************" << endl << endl; cout << " 1. " << left << setw(30) << "Sort by Student ID" << endl; cout << " 2. " << setw(30) << "Search for a Student ID and Display Grades" << endl; cout << " 3. " << setw(30) << "Search by Letter Grade" << endl; cout << " 4. " << setw(30) << "Sort by Numeric Grade" << endl; cout << " 5. " << setw(30) << "Calculate Percentage of Students for a Letter Grade" << endl; cout << " 6. " << setw(30) << "Sort Alphabetically by Student Last Name" << endl; cout << " 7. " << setw(30) << "Exit the Program" << endl << endl; cout << right << "Enter an option: " ; cin >> num; cout << endl; if (num == 1) { //cout << "This option sorts the student list by ID and writes it to a file."; insertionSort_byInteger(ids, MAXSTUDENTS); for (idx = 0; idx < MAXSTUDENTS; idx++) { cout << ids[idx] << " " << firstName[idx] << " " << lastName[idx] << " " << scores[idx] << " " << grades[idx] << endl; } } if (num == 2) { ifstream inFile4; inFile4.open(NEWFILENAME); cout << "Enter a student ID: "; cin >> target; for(idx = 0; idx < s; idx++) { inFile4 >> ids[idx] >> scores[idx] >> grades[idx]; if(ids[idx] == target) cout << "Result: " << ids[idx] << " " << scores[idx] << " " << grades[idx] << endl; //else //cout << "This ID is not found in the list. Please try again." << endl; } inFile4.close(); } else if (num == 3) { ifstream inFile5; inFile5.open(NEWFILENAME); idx = 0; while (idx <= s && !inFile5.eof()) { inFile5 >> ids[idx] >> scores[idx] >> grades[idx]; idx++; } cout << "Enter a grade: "; cin >> targetGrade; cout << endl; for(idx = 0; idx < s; idx++) { if(grades[idx] == targetGrade) cout << "Result: " << ids[idx] << " " << grades[idx] << endl; } inFile5.close(); } else if (num == 4) cout << "This option sorts the list by numeric grade."; else if (num == 5) { ifstream inFile6; inFile6.open(NEWFILENAME); idx = 0; while (idx <= s && !inFile6.eof()) { inFile6 >> ids[idx] >> scores[idx] >> grades[idx]; idx++; } cout << "Enter the letter grade to calculate %: "; cin >> targetLetter; cout << endl; for (idx = 0; idx < s; idx++) { if(grades[idx] == targetLetter) { p = p + 1; percent = (p * 100)/s; } } cout << percent << " % of the students received a " << targetLetter << "." << endl; inFile6.close(); } else if (num == 6) cout << "Sort by last name and first name."; else if (num == 7) cout << "Exit the program."; else if (num < 1 || num > 5) cout << "This is an invalid entry. Please rerun the program and try again."; cout << endl << endl << endl; } while (num > 0 && num <= 5); system("PAUSE"); return EXIT_SUCCESS; } void insertionSort_byInteger(int arrtosort[], int size) { int temp = arrtosort[0]; for(int i = 1; i <= size; i++) { temp = arrtosort[i]; int j = 0; for(j = i; j > 0; j--) if(temp < arrtosort[j - 1]) arrtosort[j] = arrtosort[j - 1]; else break; arrtosort[j] = temp; } } void insertionSort_ByString(string arrtosort[], int size) { string temp = arrtosort[0]; for ( int i = 1; i <= size; i++ ) { temp = arrtosort[i]; int j = 0; for ( j = i; j > 0; j--) if ( temp < arrtosort[j - 1]) arrtosort[j] = arrtosort[j - 1]; else break; arrtosort[j] = temp; } }``````
It's because you're only sorting the id array. All of the other arrays aren't going to get modified because you do nothing to rearrange them. In order to make this work properly, you have two choices. Create an object that contains all of the required properties that you need, or pass every array and modify them together. The first would require a small rework of somethings, but is overall easy. The second would result in you having multiple parameters and having to move a lot of information at one. Your sort function would grow a little larger (due to extra variables).

You mentioned the rest of the values are junk. Did you mean they didn't line up properly with the ids anymore (if so, check last paragraph for the fix)? Or did you mean that you're getting incoherent values for each of them (as if some random values were placed there, not the ones that should be there)?

Any other problems you're having?
This is what I'm getting as it is currently for option #1:

1000 T C 3 C
1001 h o 9 A
1002 e f 3 C
1003 o f 2 F

I have no idea where the values in column 2 and 3 are coming from. That's the junk I was referring to. The 4th and 5th column look like they do in the original file, they just aren't sorting. I'll have to figure out how to sort the other columns.
I'm not sure how you're getting the right values at all to be honest. Looking at your code (which is pretty unorganized) it looks like you open your first infile, read everything from it into temp variables, then close it. Then you open the outfile and write to it from your variables. Only this time, you use the arrays, not the original variables for infile. I don't think this requires a rewrite, but it does require a severe re-evaluation. Make sure you understand exactly what your code is doing and make sure you can justify what's going on.

Edit: Does line 92: `cout << ids[idx] << fname[idx] << lname[idx] << scores[idx] << grades[idx] << endl;` give you all of the expected results? If not, see above.
Last edited on
I haven't even looked at that menu option yet. The code below the menu is not final yet. I'm working one menu option at a time. I'm still stuck on #1 to sort everything by ID. That's the one I want to get right first, then continue down to #2. I know the rest doesn't work right yet. For the life of me I can't understand sort and this thing is due tomorrow. I've been banging my head against a wall all week. :)

Where I'm stuck now is lines 105 to 127 where menu option #1 runs. I'm getting this error now: no match for 'operator>>' in 'sortedId >> sortids[idx]'
and no match for 'operator>>' in 'sortedId>> sortids[idx]'
when I try to save the sorted ID's to an array and then compare that array to the Id array in the NEWFILENAME text file. don't understand why.

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130`` ``````void insertionSort_byInteger(int arrtosort[], int size); void insertionSort_ByString(string arrtosort[], int size); const int MAXSTUDENTS = 30; const char FILENAME[40] = "TestScores2.txt"; const char NEWFILENAME[40] = "TestScores_Grades2.txt"; const char SORTEDIDS[40] = "SortedIDs.txt"; int main() { string fname[MAXSTUDENTS]; string lname[MAXSTUDENTS]; string grades[MAXSTUDENTS]; int ids[MAXSTUDENTS], scores[MAXSTUDENTS], sortids[MAXSTUDENTS]; ifstream inFile; int id, idx, score, score2, s = 0, avg, totalgrade = 0, numofstudents = 0; int num, target, p = 0, percent; string grade, grade2, firstName, lastName, fnames, lnames, targetGrade, targetLetter; inFile.open(FILENAME); //read file and get average while (s < MAXSTUDENTS) { inFile >> id; inFile >> firstName; inFile >> lastName; inFile >> score; if (score >= 0 && score <= 10) { totalgrade = totalgrade + score; numofstudents++; } s = s + 1; } avg = totalgrade/numofstudents; //cout << "The average score is: " << avg << endl << endl; inFile.clear(); inFile.seekg(0); //read file, generate letter grade and create new file ofstream outFile1; outFile1.open(NEWFILENAME); for(idx = 0; idx < MAXSTUDENTS; idx++) { inFile >> id >> firstName >> lastName >> score; if ( score != -1 ) { if (score == avg || score == avg +1) grade = "B"; else if (score == avg + 2 || score == avg + 3) grade = "A-"; else if (score >= avg +4 || score == 10 ) grade = "A"; else if (score == avg - 1) grade = "C"; else if (score >= 0 && score <= (avg - 2)) grade = "F"; outFile1 << id << " " << firstName << " " << lastName << " " << score << " " << grade << endl; } else outFile1 << id << " " << firstName << " " << lastName << " " << score << endl; //cout << id << " " << firstName << " " << lastName << " " << score << endl; } inFile.close(); //read letter grade file and launch menu ifstream inFile2; inFile2.open(NEWFILENAME); idx = 0; while (idx < MAXSTUDENTS) { inFile2 >> ids[idx] >> fname[idx] >> lname[idx] >> scores[idx]; if ( scores[idx] != -1 ) inFile2 >> grades[idx]; cout << ids[idx] << fname[idx] << lname[idx] << scores[idx] << grades[idx] << endl; idx++; } inFile2.close(); do { cout << setw(30) << "QUIZ RESULTS MENU " << endl; cout << setw(30) << "***************************" << endl << endl; cout << " 1. " << left << setw(30) << "Sort by Student ID" << endl; cout << " 2. " << setw(30) << "Search for a Student ID and Display Grades" << endl; cout << " 3. " << setw(30) << "Search by Letter Grade" << endl; cout << " 4. " << setw(30) << "Sort by Numeric Grade" << endl; cout << " 5. " << setw(30) << "Calculate Percentage of Students for a Letter Grade" << endl; cout << " 6. " << setw(30) << "Sort Alphabetically by Student Last Name" << endl; cout << " 7. " << setw(30) << "Exit the Program" << endl << endl; cout << right << "Enter an option: " ; cin >> num; cout << endl; ofstream sortedId; ifstream inFile3; sortedId.open(SORTEDIDS); inFile3.open(NEWFILENAME); if (num == 1) { insertionSort_byInteger(ids, MAXSTUDENTS); for (idx = 0; idx < MAXSTUDENTS; idx++) { sortedId >> sortids[idx] >> fnames >> lnames >> score2; if ( score2 != -1 ) sortedId >> grade2; idx++; } sortedID.close(); ifstream sortedID; sortedID.open(SORTEDIDS); for (idx = 0; idx < MAXSTUDENTS; idx++) { if(sortids[idx] == ids[idx]) { cout << ids[idx] << fname[idx] << lname[idx] << scores[idx]; if(scores[idx] != -1) cout << grades[idx] << endl; } } }``````
Last edited on
Topic archived. No new replies allowed.