Domanda

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
È stato utile?

Soluzione

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.)

Altri suggerimenti

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.

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?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top