0

So I've been working on a project for class and everything was going swimmingly, until I had to sort the information by last name in ascending order. To elaborate further, in my program I am supposed to take file input, apply it into whatever kind of variables I see fit, calculate their grades by comparing their answers against an answer key, and then sort the entries by last name. Without further ado here is my code! (be gentle)

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <algorithm>

const int TEST_SIZE = 10;

using namespace std;

struct StudentInfo
{
int id;
string fName;
string lName;
char testAnswers[10];
int totalPoints = 0;
int avg = 0;
char letterGrade;

};



void inputInfo(char[], StudentInfo[]);
void calcGrade(char[], StudentInfo[]);
void bubbleSort(StudentInfo[]);
void outputInfo(StudentInfo[]);

int main()
{
StudentInfo studentInfo[10];
string temp;
char answerKey[10];

inputInfo(answerKey, studentInfo);
calcGrade(answerKey, studentInfo);
bubbleSort(studentInfo);
outputInfo(studentInfo);

return 0;
}

void inputInfo(char answerKey[], StudentInfo studentInfo[])
{
cout << "Please enter the 10-question answer key: \n";

for(int i = 0; i < TEST_SIZE; i++)
    {
        cout << "Question " << i+1 << "\n";
        cin >> answerKey[i];
    }

    ifstream inFile("student.txt");

    for(int i = 0; i < TEST_SIZE; i++)
        {
            inFile >> studentInfo[i].id;
            inFile >> studentInfo[i].fName;
            inFile >> studentInfo[i].lName;

            for(int j = 0; j < TEST_SIZE; j++){
            inFile >> studentInfo[i].testAnswers[j];
            }
        }
}

void calcGrade(char answerKey[], StudentInfo studentInfo[])
{
for(int i = 0; i < TEST_SIZE; i++)
    {
        for(int j = 0; j < TEST_SIZE; j++)
            {
                if(studentInfo[i].testAnswers[j] == answerKey[j])
                    {
                        studentInfo[i].totalPoints += 5;
                    }
                    studentInfo[i].avg = studentInfo[i].totalPoints * 2;

                    if(studentInfo[i].avg >= 90)
                        {
                            studentInfo[i].letterGrade = 'A';
                        }
                    else if(studentInfo[i].avg >= 80)
                        {
                            studentInfo[i].letterGrade = 'B';
                        }
                    else if(studentInfo[i].avg >= 70)
                        {
                            studentInfo[i].letterGrade = 'C';
                        }
                    else if(studentInfo[i].avg >= 60)
                        {
                            studentInfo[i].letterGrade = 'D';
                        }
                    else
                        {
                            studentInfo[i].letterGrade = 'F';
                        }
            }
        }
}

void bubbleSort(StudentInfo studentInfo[])
{
StudentInfo temp;
int i;
int j;

for(i = 0; i < (TEST_SIZE-1); i++)
    {
        for(j = 0; j < TEST_SIZE; j++)
            {
                if(studentInfo[j].lName < studentInfo[j-1].lName)
                    {
                        temp = studentInfo[j];
                        studentInfo[j] = studentInfo[j-1];
                        studentInfo[j-1] = temp;
                    }
            }
    }
}

void outputInfo(StudentInfo studentInfo[])
{
cout << setprecision(1) << fixed;

cout << "Student ID\tStudent Name\tAnswers\tTotal Pts\tAverage\t   Letter Grade" << endl;

for(int i = 0; i < TEST_SIZE; i++)
    {
        cout << studentInfo[i].id << "\t";
        cout << studentInfo[i].lName << " ";
        cout << studentInfo[i].fName << "\t";

        for(int j = 0; j < TEST_SIZE; j++)
            {
                cout << studentInfo[i].testAnswers[j];
            }
        cout << "\t" << studentInfo[i].totalPoints << "\t";
        cout << studentInfo[i].avg << "\t";
        cout << studentInfo[i].letterGrade << "\n";
    }
}

I've tried everything within my meager abilities, but my program always crashes. Assumedly during the bubble sort since it works fine without that section. If someone could enlighten me as to where I erred I would be very grateful. Sorry for any inconvenience that I've caused.

  • 1
    Run it in a debugger and it'll tell you which line causes it to crash. – user253751 Dec 02 '15 at 02:21
  • If you're going to be using arrays with constant size, use `std::array`. If they'll change in size, use `std::vector`. They should both fail an `assert` if you go out of bounds, so you can find problems like this. – Weak to Enuma Elish Dec 02 '15 at 02:25
  • @JamesRoot I think they fail the assert only if compiled with a specific debug flag, `-D_GLIBCXX_DEBUG` for g++. – vsoftco Dec 02 '15 at 02:28
  • @vsoftco True, if `NDEBUG` is defined (or maybe if `DEBUG` isn't defined, I can never remember) then assert becomes a noop. I hope the asker is trying to debug in debug mode. – Weak to Enuma Elish Dec 02 '15 at 02:32
  • 1
    @JamesRoot You have to specify `-D_GLIBCXX_DEBUG`, even if `DEBUG` is defined. I don't know if clang++ or VS support something equivalent. A C++ compliant way is to use `.at()` member function, which throws in the case of out of bound access. And after extensive testing switch back to the faster `operator[]`. Found something relevant: http://stackoverflow.com/q/1290396/3093378 – vsoftco Dec 02 '15 at 02:34
  • @JamesRoot To be entirely honest, my teacher has never taught me, told me, or even mentioned a debugger before. I was told to logically step through the program line by line by myself. – Aaron McAnally Dec 02 '15 at 02:35
  • @AaronMcAnally It's good to step through by yourself, but a debugger is an extraordinary useful tool, make sure you learn how to use it. – vsoftco Dec 02 '15 at 02:37
  • @vsoftco I'll be sure to learn how to use it on my own then. I apologize for wasting time over something that a tool could've easily solved. Thanks for the assistance. – Aaron McAnally Dec 02 '15 at 02:49
  • @AaronMcAnally You're welcome. – vsoftco Dec 02 '15 at 02:53

1 Answers1

2

What happens here

temp = studentInfo[j];
studentInfo[j] = studentInfo[j-1];
studentInfo[j-1] = temp;

when j==0? You access out of bounds. You're better off using std::swap from <algorithm> like

std::swap(studentInfo[j], studentInfo[j+1]);

making sure that you run j until TEST_SIZE - 1. Or write the "manual" swap but with j exchanged by j+1.

vsoftco
  • 55,410
  • 12
  • 139
  • 252