-4

I have a c++ program I've been working on, it displays student grades from a sequential access file, then uses the same file to calculate and display each students gpa. after calling displayGpa() it says "Run-Time Check Failure #2 - Stack around the variable 'gpa' was corrupted."

Here is the .cpp file giving me trouble:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include "sRecords.h"

using namespace std;

void sRecords::displayGpa()
{

    string firstName, lastName;
    string grade[4];
    double gpa[4];
    double finalGpa[4];
    ifstream inputFile;
    inputFile.open("studentRecords.txt");

    while (inputFile)
    {
        inputFile >> firstName >> lastName;
        int x = 0;
        while (x <=3)
        {
            inputFile >> grade[x];
            if (grade[x] == "A")
            {
                gpa[x] = 4.00;
            }
            else if (grade[x] == "A-")
            {
                gpa[x] = 3.70;
            }
            else if (grade[x] == "B+")
            {
                gpa[x] = 3.33;
            }
            else if (grade[x] == "B")
            {
                gpa[x] = 3.00;
            }
            else if (grade[x] == "B-")
            {
                gpa[x] = 2.70;
            }
            else if (grade[x] == "C+")
            {
                gpa[x] = 2.30;
            }
            else if (grade[x] == "C")
            {
                gpa[x] = 2.00;
            }
            else if (grade[x] == "C-")
            {
                gpa[x] = 1.70;
            }
            else if (grade[x] == "D+")
            {
                gpa[x] = 1.30;
            }
            else if (grade[x] == "D")
            {
                gpa[x] = 1.00;
            }
            else if (grade[x] == "D-")
            {
                gpa[x] = .70;
            }
            else
            {
                gpa[x] = 0.00;
            }
        x++;
        }
        finalGpa[x] = (gpa[0] + gpa[1] + gpa[2] + gpa[3]) / 4;
        cout << firstName << " " << lastName << " " << finalGpa[x] << endl;
    }
    inputFile.close();
}
void sRecords::displayHeader()
{
    cout << "\t-------------------------------" << endl;
    cout << "\t\tSTUDENT RECORDS" << endl;
    cout << "\t-------------------------------" << endl << endl;
}

void sRecords::printRecords()
{
    ifstream inputFile;
    inputFile.open("studentRecords.txt");

    string string1, string2, string3, string4, string5, string6;
    cout << setw(12) << left << "FIRST NAME" << setw(11) << left << "LAST NAME";
    cout << setw(9) << left << "ENGLISH" << left << setw(6) << "MATH";
    cout << setw(9) << left << "SCIENCE" << left << setw(12) << "CHEMISTRY" << endl << endl;

    while (inputFile)
    {
        inputFile >> string1 >> string2 >> string3 >> string4 >> string5 >> string6;

        cout << setw(12) << left << string1 << setw (11) << left << string2; 
        cout << setw(9) << left << string3 << setw(6) << left << string4; 
        cout << setw(9) << left << string5 << setw(12) << left << string6 << endl;
    }
    cout << endl;
    inputFile.close();
}
  • TL;DR; Sounds much like you've hit undefined behavior! – πάντα ῥεῖ Jun 15 '14 at 21:17
  • `while (inputFile)` looks like an infinite loop, I wonder how it worked the first time. If you wanna read the entire file you should do something like `while (!inputFile.eof())` – Gufino2 Jun 15 '14 at 21:28
  • @Gufino2 http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – πάντα ῥεῖ Jun 15 '14 at 21:30
  • @πάνταῥεῖ Thanks, didn't know about that. Anyway, the loop condition in the code should be fixed. – Gufino2 Jun 15 '14 at 21:41
  • @Gufino2 Why do you think it's an infinite loop? `inputFile` casted to a `bool` will well return `false` either on EOF condition, or any input failure. – πάντα ῥεῖ Jun 15 '14 at 21:45
  • @πάνταῥεῖ I guess you're right. It's been a while since I last wrote something in c++ with fstream, my memory's getting a bit rusty :) Btw, that's not infinite loop, but if it casts to false on EOF, isn't it the same thing (with the same problem) as using fileInput.eof() ? – Gufino2 Jun 15 '14 at 22:20
  • @Gufino2 You see from PaulR's answer the infinite loop was the inner one ;) ... – πάντα ῥεῖ Jun 15 '14 at 22:24
  • @πάνταῥεῖ Yeah, that's ok about the loop. But now I'm getting curious: since fstream casts to false on failure isn't `while (inputFile)` exactly as bad as `while (!inputFile.eof())` ? It won't cast to false until you actually try reading past the end-of-file. – Gufino2 Jun 15 '14 at 22:29
  • @Gufino2 If you would have read my 1st link thoroughly, you should have noticed that `ifstream::eof()` misses the other possible error conditions, and thus really could end up in an infinite loop ... – πάντα ῥεῖ Jun 15 '14 at 22:34
  • @πάνταῥεῖ sorry, maybe I'm not expressing myself clearly enough. Let's consider ifstream::fail() instead of eof(). fstream's cast to bool depends on fail() and since fail conditions are triggered after an unsuccessful read, using `while(inputFile){` as loop condition would still give an extra (unwanted) loop iteration before it quits, right? The read attempt should be performed inside the loop condition, like in `while(stream >> value) {...}` to detect the error condition BEFORE entering the loop iteration. – Gufino2 Jun 15 '14 at 22:51
  • @Gufino2 No, failbit is set on reading/parsing errors immediately. And yes, putting the actual input statement as loop condition is the correct way. – πάντα ῥεῖ Jun 15 '14 at 22:58
  • @πάνταῥεῖ thank you for your precious clarification :) – Gufino2 Jun 15 '14 at 23:04

1 Answers1

0

You have an infinite loop - it seems that you got confused about the logic of your inner and outer loop.

It looks like you need to change:

            else
            {
                gpa[x] = 0.00;
            } // end of if/else
        } // end of inner while loop
        finalGpa[x] = (gpa[0] + gpa[1] + gpa[2] + gpa[3]) / 4;
        cout << firstName << " " << lastName << " " << finalGpa[x] << endl;
        x++;
    } // end of outer while loop

to:

            else
            {
                gpa[x] = 0.00;
            } // end of if/else
            finalGpa[x] = (gpa[0] + gpa[1] + gpa[2] + gpa[3]) / 4;
            cout << firstName << " " << lastName << " " << finalGpa[x] << endl;
            x++;
        } // end of inner while loop
    } // end of outer while loop
Paul R
  • 195,989
  • 32
  • 353
  • 519