#I want to know if theres a better way to write my code

48 messages · Page 1 of 1 (latest)

whole pikeBOT
#

When your question is answered use !solved or the button below to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

thorny comet
#

Switch statements?

open hound
#

This program obtains a series of letter grades as input from a user. The program should calculate and output the total grade points and the grade point average (note: you may have to track the total number of inputs and the grade points to calculate the grade point average). The
algorithm should execute 3 times for testing purposes.
Use the appropriate loop for the main structure of the program that will stop accepting letter
grades when the user inputs X. Also, choose the appropriate selection statement to convert the
letter grade to the correct grade points.

open hound
#

also do you think there is a better way to initalize totalPoints = 0.0;
gradePoints = 0.0;
gradeNum = 0;
displayNum = gradeNum + 1; instead of in the for loop

thorny comet
# thorny comet Switch statements?
#define RUN_NUMS 3

for (int testNum = 1; testNum <= RUN_NUMS; testNum = testNum + 1)
    {
        double totalPoints = 0.0;
        double gradePoints = 0.0;
        int gradeNum    = 0;

        printf("Test Case #%d\n", testNum);   

        char userGrade;
        while (usersGrade != 'X')
        {

            printf("Enter Letter Grade#%d ", &(++gradeNum));
            scanf("%c", &usersGrade);
            usersGrade = toupper(usersGrade);

            switch (userGrade) {
                case 'A' : gradePoints = 4.0; break;
                case 'B' : gradePoints = 3.0; break;
                case 'C' : gradePoints = 2.0; break;
                case 'D' : gradePoints = 1.0; break;
                case 'F' : gradePoints = 0.0; break;
            }

            totalPoints += gradePoints;
        }

        if (gradeNum > 0)
        {
            double gpa = totalPoints / gradeNum;

            printf("\nTotal Grade Points: %d\n", totalPoints);
            printf("GPA: %d\n", gpa);
        }

        printf("\n\n");
    }
}
#

What abt this @open hound

open hound
thorny comet
#

1 sec

#
constint int RUN_NUMS = 3;

for (int testNum = 1; testNum <= RUN_NUMS; testNum = testNum + 1)
    {
        double totalPoints = 0.0;
        double gradePoints = 0.0;
        int gradeNum    = 0;

        cout << "Test Case #" << testNum << "\n";

        char userGrade;
        while (usersGrade != 'X')
        {

            cout << "Enter Letter Grade# " << ++gradeNum;
            cin >> userGrade;
            usersGrade = toupper(usersGrade);

            switch (userGrade) {
                case 'A' : gradePoints = 4.0; break;
                case 'B' : gradePoints = 3.0; break;
                case 'C' : gradePoints = 2.0; break;
                case 'D' : gradePoints = 1.0; break;
                case 'F' : gradePoints = 0.0; break;
            }

            totalPoints += gradePoints;
        }

        if (gradeNum > 0)
        {
            double gpa = totalPoints / gradeNum;

            cout << "\n" 
            << "Total Grade Points: " << totalPoints << "\n" 
            << "GPA: " << gpa << "\n";
        }

        cout << "\n\n"
    }
}
#

What abt this?

#

I swapped endl to "\n" to reduce the overhead

open hound
#

for us we havent gotten to using define so is there a way to do it as a const

open hound
thorny comet
#

I jst forgot to add them back here

open hound
#

for some reason when it gets to test case #2 it shows 18.000 instead of just 18

open hound
thorny comet
#

My forgetfulness?

open hound
thorny comet
#

I think thats just a flaw of u using float types

open hound
thorny comet
# open hound is defaultfloat the best solution then

Try this ```cpp
constexpr int RUN_NUMS = 3;
using std::cin, std::cout;

for (int testNum = 1; testNum <= RUN_NUMS; testNum = testNum + 1)
{
int totalPoints = 0;
double gradePoints = 0.0;
int gradeNum = 0;

    cout << "Test Case #" << testNum << "\n";

    char userGrade;
    while (userGrade != 'X')
    {

        cout << "Enter Letter Grade# " << ++gradeNum;
        cin >> userGrade;
        userGrade = toupper(userGrade);

        switch (userGrade) {
            case 'A' : gradePoints = 4.0; break;
            case 'B' : gradePoints = 3.0; break;
            case 'C' : gradePoints = 2.0; break;
            case 'D' : gradePoints = 1.0; break;
            case 'F' : gradePoints = 0.0; break;
            case 'X' : break;
            default: cout << "Invalid Choice" << userGrade << "\n";
        }

        totalPoints += gradePoints;
    }

    if (gradeNum > 0)
    {
        double gpa = totalPoints / gradeNum;

        cout << "\n" 
        << "Total Grade Points: " << totalPoints << "\n" 
        << "GPA: " << gpa << "\n";
    }

    cout << "\n\n";
}
inland flame
#
  if (usersGrade == 'A')
                gradePoints = 4.0;

            if (usersGrade == 'B')
                gradePoints = 3.0;

            if (usersGrade == 'C')
                gradePoints = 2.0;

            if (usersGrade == 'D')
                gradePoints = 1.0;

            if (usersGrade == 'F')
                gradePoints = 0.0;

Using using namespace std; is asking for trouble if that's what you did.
Generally avoid because it include all the names in the scope, where names can repeat and collide creating compile errors.

RUN_NUMS should best be an constexpr rather than const, though compiler will optimize it anyway... this is semantically a little bit better because you just label a value that can exist only at compile time and the program is just fine no matter the case.
It's kinda weird that it exists in the first place, but if that's in the specification then that's fine.

Nice that you cared about letter case, as you always should.

If there's only one possibility then it should be if...else
You can create an array for those so you don't have to use if at all, for once that would reduce it only to bounds checking which you don't seem to even have in your solution.
I would say that for the future of the program you could even consider creating a function for translating grades expressed with letters to grades expressed with float (but that's a side note, maybe the program is not expected to change).

In case of

if (gradeNum > 0)

Overall may be necessary, or may not be and in such case you can consider non-nesting version of it.
Since we are in a loop we can just check for inversed condition and skip execution of code below (assuming nothing else needs to happen below it).

if (gradeNum <= 0) continue;

gpa = totalPoints / gradeNum;
// ...
cout << endl << endl;

Very often this trick saves you from nesting too many things like:

if (x) {
  if (y) {
    for (...) {
      if(d) {
      }
    }
  }
}
open hound
#

One of the steps said thhe algorithm should execute 3 times for testing purposes so thats why i included RUN_NUMS was that not necessary?

inland flame
#

Entire while (userGrade != 'X') (btw. shouldn't you also use toupper for it?)
could be a function, the task repeats, it will always give you same type of input no?
You can just make function that executes whatever is inside the execution block of this loop.
Not sure if specification allows but you should probably give more feedback on user input in some cases.

inland flame
#

What I mean that normally you want to have many tests (but unknown amount of tests), and add them easily and so having constant for it doesn't make sense in real life situations.

open hound
#

ahh that makes sense do you think me using a switch statement instead of multiple if statements will be better overall

#

because I have to make a flow chart too so i was wondering

inland flame
#

wdym by that?

open hound
# inland flame wdym by that?

instead of
if (usersGrade == 'A')
gradePoints = 4.0;

        if (usersGrade == 'B')
            gradePoints = 3.0;

        if (usersGrade == 'C')
            gradePoints = 2.0;

        if (usersGrade == 'D')
            gradePoints = 1.0;

        if (usersGrade == 'F')
            gradePoints = 0.0;

i used switch(usersGrade)
{
case 'A' : = gradePoints = 4.0;
break;

inland flame
#

Yeah that I understand but what does flow chart have to do with this?

open hound
#

but for my actual program is the switch statement better?

inland flame
#

Overall whichever you prefer, in this case does not make much of a difference but I do think it's cleaner to use switch here.
Generally when there is a very limited number of options and they can be easily define with simple numeric values, without ranges etc. I think switch conveys this idea better.

If you know enum class then it makes even more sense to use switch because it forces you to exhaust all possible options while if...else does not.
Compiler will enforce this and error if you don't have defined behaviour for all options.

open hound
inland flame
#

So you want to output only integer value?
You can just convert float to apropriate integer type and display it instead.

open hound
#

how would that look instead of
if (gradeNum > 0)
{
gpa = totalPoints / gradeNum;

cout << endl
cout << "Total Grade Points: " << defaultfloat << setprecision(10) << totalPoints << endl
cout << "GPA: " << fixed << setprecision(2) << gpa << endl;

inland flame
#

Or just do this instead:

#include <cmath> // math library, do it at the top
//...

//
std::floor(name_of_float_variable) // rounds downwards so even 1.7 will end up 1.0

If you did not force display of values past . then it should display without it.

#

You can also cast it to integer instead:

// make sure integer type here is enough to hold the value
static_cast<int>(name_of_float_variable)
#

Mind that float can hold very weird values that int cannot like inf or NaN.
Those won't be properly converted.

#

They have different representation in memory so you have to account for them in some cases.

urban shuttle
#

you could also use a lookup table like std::unordered_map

``
#include <unordered_map>
#include <string>

std::unordered_map<std::string, float> grades =
{
    {"A", 4.f},
    {"B", 3.f}...
};

if (userGrade == "X") { ... }
else if (grades.count(std::string(userGrade)))
{
    totalPoints += grades.at(std::string(userGrade));
}
else
    std::cout << "Invalid input" << std::endl;

``