-1

Hi so I started to create a program to calculate a person's GPA and save that info for future reference. My problem is that I can't figure out how to read the numbers saved in the .txt file and then store them for GPA calculating purposes. Here is the unfinished program's code and any help would be great

EDIT: The .txt file is laid out like this: 5.0 3.7 5.0 3.7 5.0 4.0 ... Below is my progress in the program but when I run it I receive a GPA of 0 (incorrect). Not sure if the lexical cast is my problem, the getline() method or something else. Any help (the calculateGPA() method is the trouble area)?

#include <iostream>
#include <fstream>
#include <string>
#include <boost/lexical_cast.hpp>
using namespace std;

string newCC, newCG;
double curGPA;
char command;
bool running = 1;

void calculateGPA();
void writeGrades();
void mainMenu();
void addClass();

int main()
{
    while(running) {
        mainMenu();
    }

    return 0;
}

void calculateGPA()
{
    double credit_sum = 0.0, grade_sum = 0.0;
    double credit, grade;

    ifstream gReader("grades.txt");

    for( int i = 0; ! gReader.eof() ; i++ )
    {
        string number;

        getline( gReader , number ) ;

        double dblNumber;
        try
        {
         dblNumber = boost::lexical_cast<double>(number);
        }
        catch (boost::bad_lexical_cast const&)
        {
              dblNumber = 0;
        }

        credit_sum = credit_sum + dblNumber;
    }

    ifstream cReader("credits.txt");

    for( int i = 0; ! cReader.eof() ; i++ )
        {
            string number;

            getline( cReader , number ) ;

            double dblNumber;
            try
            {
             dblNumber = boost::lexical_cast<double>(number);
            }
            catch (boost::bad_lexical_cast const&)
            {
                  dblNumber = 0;
            }
            credit_sum = credit_sum + dblNumber;
        }

    if(credit_sum == 0.0) {

        curGPA = 0.0;
    }

    curGPA = (grade_sum / credit_sum);

  cReader.close() ;
  gReader.close() ;

}//End calculateGPA

void writeGrades()
{
    string cToWrite = newCC + "\n"; 
    string gToWrite = newCG + "\n";

    ofstream cWriter("credits.txt", ios::app);
    cWriter << cToWrite;
    ofstream gWriter("grades.txt", ios::app);
    gWriter << gToWrite;

    cWriter.close();
    gWriter.close();
}//End writeGrades

void addClass()
{
    cout << "New class' credits?"; cin >> newCC;
    cout << endl << "New class' grade? (GP)"; cin >> newCG;
    writeGrades();
    cout << "Add another class? (y/n)" << endl; cin >> command;
    if(command == 'y')
        addClass();
    else mainMenu();
}//End addClass

void mainMenu()
{
    string command;

    cout << "What would you like to do?" << endl;
    cout << "(V)iew GPA" << endl;
    cout << "(A)dd grades" << endl;
    cout << "(E)xit" << endl;

    cin >> command;

    if(command == "v")
    {
        calculateGPA();
        cout << "Your current GPA is " << curGPA << endl;
    }
    else if(command == "a")
    {
        addClass(); 
    } 

    else running = 0;

}//End mainMenu

3 Answers3

0

Look at this function: http://www.cplusplus.com/reference/cstdlib/atof/

You could use it to convert the string (or char) being read in into a double. I assume you want double because grades are 4.0, 3.7, 3.3, 3.0, etc.

sbru
  • 877
  • 6
  • 21
  • 36
  • atof (and atoi) don't provide any reliable way to check for failure. For this reason, I would recommend scanf if you want to do it the C way. – Jonathan Baldwin Apr 29 '13 at 02:19
0

Using streams:

double calculateGPA() {
    double credit_sum = 0.0, grade_sum = 0.0;
    double credit, grade;
    ifstream reader("grades.txt");

    while (!reader.eof()) { /* while the file still has numbers to be read */
        reader >> credit >> grade;

        if (reader.fail()) {
            /* something unexpected happened (read error/formatting error) */
            break;
        }

        credit_sum += credit;
        grade_sum += grade;
    }

    if(credit_sum == 0.0) {
        /* avoid divide by zero */
        return 0.0;
    }

    /* divide the total grade by the total credits */
    return grade_sum / credit_sum;
}

Notes:

  • Assumes .txt file just has numbers (credits, grade, credits, grade, ...) delimited by whitespace (spaces or line breaks): For more complicated formatting you want scanf or regex.
  • Returns double instead of float, you usually want double's precision over float's relatively small speed and memory advantage.
  • File will be closed at the end of the function, when reader goes out of scope. reader.close() is not necessary, but wouldn't be a bad thing to put in (I'm just lazy.)
  • Thanks for the reply. The .txt file follows the format: 5.0 3.7 5.0 3.7 5.0 4.0 and so on in a long list. I need to multiply the 1st number by the 2nd number and store that value, then multiply the 3rd number by the 4th number and store that value and so on. How would I accomplish this (I'm thinking some kind of loop but not sure how) – Techmaster37 Apr 29 '13 at 02:55
  • Updated my answer to a working solution of what I *think* you want. According to Wikipedia "GPA is calculated by taking the number of grade points a student earned in a given period of time divided by the total number of credits taken." Updated solution does just that. – Jonathan Baldwin Apr 29 '13 at 06:58
  • Thanks so much. I punched in the code and the program runs but the GPA it calculated was 0.86129. Everything in your code made sense to me except the 'reader >> credit >> grade;' line. How does it work and what are some possible alternatives. Thanks so much for your help – Techmaster37 Apr 30 '13 at 01:01
  • Sorry for the (very) late reply. In case you haven't figured what 'reader >> credit >> grade' does, it reads credit from the file, then it reads grade from the file, ignoring any whitespace in between. The >> operator on an input stream extracts a value into a variable then "returns" the input stream, which can be used for another extraction. – Jonathan Baldwin May 12 '13 at 03:43
  • Also, 0.86129 smells right: 86% average. Convert that accordingly to whatever GPA scale you want. At my university, GPAs go from 0 to 10 and are not weighted, so I would simply multiply that by 10. – Jonathan Baldwin May 12 '13 at 03:55
  • Thanks for the help. I've reverted the code back from what I edited in above; your code produced better results. – Techmaster37 May 14 '13 at 03:32
0

Or, you can read into a double directly.

calculateGPA()
{
   double credit;
   ...
   reader >> credit;
   ...
}

Also, in your WriteGrades function, why are you writing out new lines (use endl instead of '\n') before your line instead of at the end?

Serge Ivanoff
  • 184
  • 1
  • 5