Search code examples
c++codeblocksconsole-output

Debugger has correct output but normal execution does not


I'm having this strange issue where my code does exactly what I want it to when I run it through my debugger, but it doesn't work when I run it normally. What's stranger is that I am not getting a runtime error either. This is where the issue might be, but I'm not 100% sure on this:

void calcMostMissed (double *ptr, int totalContestants, int arrSize)
{
    //output header
    cout << endl << "MOST MISSED QUESTIONS" << endl;

    //check how many times a question is missed and its percentage, then output it if it's above 60%
    double curQuest = *ptr;
    int freq = 0;
    int j = 0;
    double percentMissed;
    for (int i = 0; i <= arrSize; i++)     //loop through the missed questions array
    {
        if (*(ptr + i) > 0)      //if pointer is pointing at a question number (extra space in array is set to 0)...
        {
            if (*(ptr + i) == curQuest)      //then check how often it occurs in the array
            freq++;
        }
        else    //if the pointer is not pointing at a question number anymore...
        {
            //calculate percent missed and output it if its 60% or greater
            percentMissed = (static_cast<double>(freq) / totalContestants) * 100;
            if (percentMissed >= 60)
            {
                cout << static_cast<int>(curQuest) << "\t" << fixed << setprecision(2) << percentMissed << "%" << endl;
            }
            // check if the question's percentage missed has already been calculated and evaluated
            j++;
            curQuest = *(ptr + j);
            int r = 0;
            while (r < j)
            {
                if (*(ptr + r) == curQuest)
                {
                    if (j < arrSize - 1)
                    {
                        j++;
                        curQuest = *(ptr + j);
                    }
                }
                r++;
            }
            if (!(j == arrSize - 1 && r == arrSize - 1))
            {
                i = 0;
            }
            freq = 0;
        }
        //if the current question variable has been through all missed question, then leave loop
        if (curQuest < 1)
        {
            break;
        }
    }
}

What this function is supposed to do overall is find the percent missed on all missed questions and output only the ones that are above 60% inclusive.

This is what my debugger outputs (and what I want it to look like):

Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C

0012387654 - 0.00
1 2 3
C A B
A B C

0012364213 - 0.00
1 2 3
C A B
A B C

Mean: 0.00
Median: 0.00
Mode: 0.00

MOST MISSED QUESTIONS
1       100.00%
2       100.00%
3       100.00%

This is what a normal execution ouputs:

Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C

0012387654 - 0.00
1 2 3
C A B
A B C

0012364213 - 0.00
1 2 3
C A B
A B C

Mean: 0.00
Median: 0.00
Mode: 0.00

MOST MISSED QUESTIONS

Process returned 0 (0x0)   execution time : 14.442 s
Press any key to continue.

My debugger runs through all the way to the end of my program just fine, but for some reason the normal execution is still flawed. Any suggestions are welcome and I'll clarify anything that I may have forgotten to mention.

If it helps, I am using Code::Blocks as my IDE

Some other info about my code: there are 3 questions and all contestants scored a 0% on the test, meaning all questions have the incorrect answers.

Output: The numbers are the contestant's ID, next to that is their score, the list of numbers underneath is the question number they got wrong, underneath that are the contestant's answers, and under that are the correct answers.

This is the function that calls the calcMostMissed function:

void statReport (double *ptr, int totalScores, double *mmqPtr, int arrSize)
{
    //calculate mean of scores
    double mean = calcMean(ptr, totalScores);

    //calculate median of scores
    double median = calcMedian(ptr, totalScores);

    //calculate mode of scores
    double *mode = calcMode(ptr, totalScores);

    //output to console the data
    cout << "Mean: " << fixed << setprecision(2) << mean << endl;
    cout << "Median: " << median << endl;
    cout << "Mode: ";
    sort(mode, mode + totalScores);
    int j = 0;
    for (int i = 0; i < totalScores; i++)
    {
        if (*(mode + i) != -1)
        {
            if (j == 0)
            {
                cout << *(mode + i);
            }
            else
            {
                cout << ", " << *(mode + i);
            }
            j++;
        }
    }
    cout << endl;

    //call calcMissedQuestions function
    calcMostMissed(mmqPtr, totalScores, arrSize);

    //delete pointers
    delete[] mode;
    mode = nullptr;
    delete[] mmqPtr;
    mmqPtr = nullptr;
}

And this is the main function:

int main()
{
    string answerKeyName;
    string contestantAnswerName;
    ifstream answerKeyFile;
    ifstream contestantAnswerFile;

    //ask for file names
    cout << "Enter name of answer key file: ";
    cin >> answerKeyName;
    cout << "Enter name of contestant's answers file: ";
    cin >> contestantAnswerName;

    //check if files can be opened properly
    answerKeyFile.open(answerKeyName, ios::binary);
    contestantAnswerFile.open(contestantAnswerName, ios::binary);
    if(!answerKeyFile)
    {
        cout << "Answer key file could not be opened" << endl;
        exit(EXIT_FAILURE);
    }
    if (!contestantAnswerFile)
    {
        cout << "Contestant's answers file could not be opened" << endl;
        exit(EXIT_FAILURE);
    }

    //find how many contestant's there are
    int i = 0;
    string temp;
    while (contestantAnswerFile.good())
    {
        getline(contestantAnswerFile, temp);
        if (temp != "")
        {
            i++;
        }
    }
    contestantAnswerFile.clear();
    contestantAnswerFile.seekg(0, ios::beg);

    //create contestant's score array
    double *scorePtr = new double[i];

    //create pointer for all missed questions
    double *mmqPtr = nullptr;
    int arrSize;

    //compare the contestant's answers to the answer key, then fill array with score
    double score;
    for (int c = 0; c < i; c++)
    {
        score = compareAnswers (contestantAnswerFile, answerKeyFile, mmqPtr, i, arrSize);
        *(scorePtr + c) = score;
    }

    //create the statistics report
    statReport(scorePtr, i, mmqPtr, arrSize);

    //delete dynamically allocated array
    delete[] scorePtr;
    scorePtr = nullptr;

    //close files
    answerKeyFile.close();
    contestantAnswerFile.close();

    return 0;
}

Solution

  • Below is where I think the issue resides, however I still cannot properly compile it because other functions and input files are not provided, probably rightly so in order not to further congest the question:

    double *mmqPtr = nullptr; is defined in main(), then it's passed to the statReport() function without having been associated with any object. Afterward it acts as first parameter for function calcMostMissed() and gets dereferenced inside it, but is still a nullptr, so this produces undefined behaviour.

    There is also the issue of an out-of-bounds index inside a loop, as pointed at in the comments.