-3

Below I have my current code for a project I am working on. It is meant to take a file of students and their grades, average the grades, and then place them all back into an output file. The amount of students should not exceed 10, so if there is more than 10 students it should only read the first 10 then reverse the order. My code works perfectly excpepty when given a file with more than 10 students. It appears it is trying to access a part in memory that doesn't exist. I tried getting the code to ignore empty lines, which it should, but that doesn't seem to fix it. My "read" function is where I believe the problem is.

#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>

using namespace std;

//My student structure that holds the variable for each student object.
struct Student
{
    string fname;
    string lname;
    double average;
};

//Prototyping the functions to read the input file into an array and then reverse it.
int read(ifstream &fin, Student s[]);

void print(ofstream &fout, Student s[], int amount);

void reverse(Student s[], int amount);

int main()
{
    //Creating the file streams and global constant for the array and the filling it with I/O.
    const int size = 10;
    ifstream fin;
    ofstream fout;
    string inputFile;
    string outputFile;
    Student s[size];

    cout << "Enter input filename: ";
    cin >> inputFile;
    cout << "Enter output filename: ";
    cin >> outputFile;

    //opeining the files given by the user and then testing if the opened.
    fin.open(inputFile.c_str());
    fout.open(outputFile.c_str());

    if(fin.fail()) {
        cout << "Unable to open input file.\n";
        return 1;
    }


    //calling my 3 functions and then returning to main(). Closing files as well.
    int count = read(fin , s);
    reverse(s, count);
    print(fout, s, count);
    count = 0;

    fin.close();
    fout.close();

}

//This function reads the file given and breaks it up using string stream. It then calculates the averages for each stuent and assigns it to the array.
int read(ifstream &fin, Student s[])
{
    istringstream sin;
    string line;
    string firstName;
    string lastName;
    double score;
    double total;
    double i=0;
    int totalStudents=0;
    Student stu;
    for(int j = 0; j < 10; j++){
    while(getline(fin, line)){
        sin.clear();

        if(line.empty())
        {
            j--;
        }else{
            sin.str(line);
        while(sin >> firstName >> lastName){
            stu.fname = firstName;
            stu.lname = lastName;

            while(sin >> score){
            total += score;
            i++;
            stu.average = (total/i);
            }
        }
        s[totalStudents]=stu;
        totalStudents++;
        stu.average = 0;
        total = 0;
        i = 0;

    }
    }
    }

    //returning the number of students in the file so it can later be used for the variable of total students.
    return totalStudents;
}

//My print function that puts the array into a given output file.
void print(ofstream &fout, Student s[], int amount)
{
    for(int i = 0; i<amount; i++)
    {
        if(s[i].lname.empty())
        {
            fout<<"No students to report.";
        }else{
        ostringstream sout;
        sout << s[i].lname.c_str() << ", " << s[i].fname.c_str();
        fout <<setw(21)<< left << sout.str() << setprecision(2) << fixed << "= " << s[i].average << '\n';
    }
    }
}

//the function that reverses the order of the students by copying the last student into a temporary variable and casting it to the beggining.
void reverse(Student s[], int amount)
{
    Student temp;
    for(int i=0; i< amount/2; i++)
    {

        temp=s[i];
        s[i]=s[amount-i-1];
        s[amount - i - 1] = temp;
    }
}
  • 4
    `for(int j = 0; j < 10; j++){ while(getline(fin, line)){` That looks fishy – AndyG Nov 02 '16 at 19:04
  • 2
    The right tool to solve such problems is your debugger. You should step through your code line-by-line *before* asking on Stack Overflow. For more help, please read [How to debug small programs (by Eric Lippert)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). At a minimum, you should \[edit] your question to include a [Minimal, Complete, and Verifiable](http://stackoverflow.com/help/mcve) example that reproduces your problem, along with the observations you made in the debugger. – πάντα ῥεῖ Nov 02 '16 at 19:07

1 Answers1

0

It looks to me that after finding the empty line you should try using a continue statement, instead:

for (int j = 0; j < 10; j++) {
    while (getline(fin, line)) {
        sin.clear();

        if (line.empty())
        {
            continue;
        }
        else {
            sin.str(line);
            while (sin >> firstName >> lastName) {
                stu.fname = firstName;
                stu.lname = lastName;

                while (sin >> score) {
                    total += score;
                    i++;
                    stu.average = (total / i);
                }
            }
            s[j] = stu;
            stu.average = 0;
            total = 0;
            i = 0;

        }
    }
}

As per comments, I missed that about the for loop. It can be eliminated altogether and just have the while loop and a counter:

int j = 0;
while (getline(fin, line) && j < 10)
{
    sin.clear();

    if (line.empty())
    {
        continue;
    }
    else
    {
        sin.str(line);
        while (sin >> firstName >> lastName)
        {
            stu.fname = firstName;
            stu.lname = lastName;

            while (sin >> score)
            {
                total += score;
                i++;
                stu.average = (total / i);
            }
        }
        s[j] = stu;
        stu.average = 0;
        total = 0;
        i = 0;
        j++;
    }
}
tinstaafl
  • 6,908
  • 2
  • 15
  • 22
  • Probably won't help. OP would still need to break out of the inner while loop after reading a student somehow. – AndyG Nov 02 '16 at 19:18
  • I think my problem might be with the totalStudents variable. The max size of the array is 10 but I think the while loop will try and exceed the value of 10 because totalStudents keeps increasing. I don't know how to change that without creating an infinite loop. – Michael Santoro Nov 02 '16 at 19:25
  • @AndyG - oops my bad, didn't look at it close enough. I added better code, which should help. – tinstaafl Nov 02 '16 at 19:31
  • Thank you so much, I added a counter for totalstudents and made sure it was less than 10, the limit. Appreciate the help. – Michael Santoro Nov 02 '16 at 19:35