3
\$\begingroup\$

I'm a CS Student and I've coded a program to compute Grade Point Average (a metric used in the US for a student's performance across the curriculum). I'm looking for your suggestions and comments for my code.

I used sentinel controlled loop and for loop. Is there any way for improvement??

//Sentinel-Controlled GPA Calculator
#include <iostream>
using namespace std;
int main()
{
    float marks, points, hours, totalp=0, totalh=0, gpa;
    string course;
    cout<<"Welcome to GPA Calculator"<<endl;
    for(int i=0;;i++){
        cout<<"Enter Course "<<"#"<<i+1<<" name: ";
        cin>>course;
        if (course=="stop")
        break;
            cout<<"Enter "<<course<<" Credit Hours: ";
            cin>>hours;
            mark:
            cout<<"Enter "<<course<<"'s marks from 60 to 100: ";
            cin>>marks;
            if (marks<=100 && marks>=95)
                points = hours*5.00;
            else if (marks<95 && marks>=90)
                points = hours*4.75;
            else if (marks<90 && marks>=85)
                points = hours*4.50;
            else if (marks<85 && marks>=80)
                points = hours*4.00;
            else if (marks<80 && marks>=75)
                points = hours*3.50;
            else if (marks<75 && marks>=70)
                points = hours*3.00;
            else if (marks<70 && marks>=65)
                points = hours*2.50;
            else if (marks<65 && marks>=60)
                points = hours*2.00;
            else {
                cout<<"Please Enter Correct marks"<<endl;
                goto mark;
            }
            totalp+=points;
            totalh+=hours;
        }
    gpa = totalp/totalh;
    cout<<"Your GPA is: "<<gpa;
    }
\$\endgroup\$
4
  • \$\begingroup\$ You probably need to explain that initialism "GPA". Something to do with student work, by the look of it? \$\endgroup\$ Mar 10, 2022 at 11:19
  • \$\begingroup\$ @TobySpeight GPA = Grade Point Average. It's a metric used in the US for a student's performance across the curriculum \$\endgroup\$
    – Hugo Buff
    Mar 10, 2022 at 11:22
  • \$\begingroup\$ Thanks @Hugo. I'll edit that into Basim's question. \$\endgroup\$ Mar 10, 2022 at 11:25
  • \$\begingroup\$ @TobySpeight Thank you so much 🖤 \$\endgroup\$ Mar 10, 2022 at 11:55

1 Answer 1

2
\$\begingroup\$

Stop using namespace std; - bringing everything defined in std into the global namespace can lead to breakage (particularly if you later include more standard headers or move to a newer C++ version).

We're missing the necessary include (<string>) to define std::string.

We don't need to flush output anywhere here, so we can replace std::endl with plain newline ('\n').

The prompt should tell the user how to stop.

Instead of prompting with i+1, it's easier to start i at 1, keeping its meaning clear.

When reading from std::cin or any other stream outside the program's control, it's important not to use the results unless the read was successful. In this code, we never check whether input was read successfully, so the contents of course, hours and marks cannot be used with any confidence.

The indentation is screwy here:

    if (course=="stop")
    break;
        cout<<"Enter "<<course<<" Credit Hours: ";
        cin>>hours;

Good tools exist to fix that automatically.

The big if/else chain is probably better moved out to a function, to reduce the duplication:

#include <stdexcept>

static double multiplier_for(double marks)
{
    if (marks < 60 || marks > 100) {
        throw std::domain_error("Marks should be in range 60-100");
    }
    if (marks < 65) { return 2.00; }
    if (marks < 70) { return 2.50; }
    if (marks < 75) { return 3.00; }
    if (marks < 80) { return 3.50; }
    if (marks < 85) { return 4.00; }
    if (marks < 90) { return 4.50; }
    if (marks < 95) { return 4.75; }
    return 5.00;
}

Then we can use it within main():

    double points = hours * multiplier_for(marks);

We'll have to catch the exception; we don't need goto to repeat the prompt and input. We can use a loop which terminates when there's no exception:

    for (;;) {
        try {
            std::cout << "Enter " << course << "'s marks from 60 to 100: ";
            double marks;
            std::cin >> marks;

            double points = hours * multiplier_for(marks);
            totalp += points;
            totalh += hours;
            break;              // if no exception thrown
        } catch (std::exception& e) {
            std::cout << e.what() << '\n';
        }
    }

The final output should be a full line (ending in \n):

std::cout << "Your GPA is: " << gpa << '\n'

Modified program

This includes a robust input-retry loop, which is surprisingly hard to do well. We might consider creating a function to retry each input separately, of course:

#include <iostream>
#include <limits>
#include <stdexcept>
#include <string>

static double multiplier_for(double marks)
{
    if (marks < 60 || marks > 100) {
        throw std::domain_error("Marks should be in range 60-100");
    }
    if (marks < 65) { return 2.00; }
    if (marks < 70) { return 2.50; }
    if (marks < 75) { return 3.00; }
    if (marks < 80) { return 3.50; }
    if (marks < 85) { return 4.00; }
    if (marks < 90) { return 4.50; }
    if (marks < 95) { return 4.75; }
    return 5.00;
}


int main()
{
    std::cout << "Welcome to GPA Calculator\n";
    std::cin.exceptions(std::ios_base::badbit|std::ios_base::failbit);

    double totalh = 0;
    double totalp = 0;

    for (unsigned int i = 1;  !std::cin.eof();  ++i) {
        for (;;) {
            try {
                std::cout << "Enter Course #" << i << " name ('stop' to finish): ";
                std::string course;
                std::cin >> course;
                if (course == "stop") {
                    break;
                }

                std::cout << "Enter " << course << " Credit Hours: ";
                double hours;
                std::cin >> hours;

                std::cout << "Enter " << course << "'s marks from 60 to 100: ";
                double marks;
                std::cin >> marks;

                totalh += hours;
                totalp += hours * multiplier_for(marks);
                break;              // if no exception thrown
            } catch (std::exception& e) {
                std::cout << e.what() << '\n';
                if (std::cin.eof()) { break; }
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            }
        }

    }

    double gpa = totalp / totalh;
    std::cout << "Your GPA is: " << gpa << '\n';
}
\$\endgroup\$
2
  • \$\begingroup\$ Sometimes you might want to comment on complexity. \$\endgroup\$
    – pacmaninbw
    Mar 10, 2022 at 13:57
  • \$\begingroup\$ More functions :-0 \$\endgroup\$ Mar 10, 2022 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.