Brendaa
Brendaa

Reputation: 1

Is there a way to simplify/shorten if else statements?

Below is the problem I was asked to solve.

Create a change-counting game that gets the user to enter the number of coins required to make exactly one dollar. The program should ask the user to enter the number of pennies, nickels, dimes, and quarters. If the total value of the coins entered is equal to one dollar, the program should congratulate the user for winning the game. Otherwise, the program should display a message indicating whether the amount was more than or less than one dollar.***

I was able to make my program run, but I feel like the nested if/else statements can get a bit confusing. Is there a way to shorten it or make it easier to read? I thought about using more else if statements but couldn't figure out how that would work.

This is my code:

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int pennies, nickels, dimes, quarters;
    double penniesTotal, nickelsTotal, dimesTotal, quartersTotal, coinsTotal;

    cout << "Enter a quantity of coins needed to make EXACTLY one dollar.\n";

    cout << "\nEnter the amount of pennies: ";
    cin >> pennies;
    
    // ensures user enters amount of pennies greater than or equal to zero
    if (pennies < 0)
        cout << "\nAmount of pennies must be greater than or equal to zero!";
    else
    {
        penniesTotal = pennies * 0.01;

        cout << "\nEnter the amount of nickels: ";
        cin >> nickels;

        // ensures user enters amount of nickels greater than or equal to zero
        if (nickels < 0)
            cout << "\nAmount of nickels must be greater than or equal to zero!";
        else
        {
            nickelsTotal = nickels * 0.05;

            cout << "\nEnter the amount of dimes: ";
            cin >> dimes;


            // ensures user enters amount of dimes greater than or equal to zero
            if (dimes < 0)
                cout << "\nAmount of dimes must be greater than or equal to zero!";
            else
            {
                dimesTotal = dimes * 0.10;

                cout << "\nEnter the amount of quarters: ";
                cin >> quarters;

                // ensures user enter amount of quarters greater than or equal to zero
                if (quarters < 0)
                    cout << "\nAmount of quarters must be greater than or equal to zero!";
                else
                {
                    quartersTotal = quarters * 0.25;

                    // adds all coins together
                    coinsTotal = penniesTotal + nickelsTotal + dimesTotal + quartersTotal;

                    // identifies if coins are less than, greater than, or equal to $1.00
                    if (coinsTotal == 1.00)
                        cout << "\nCONGRATULATIONS!\n" <<  "Your selection of coins adds up to $1.00.\n";
                    else if (coinsTotal < 1.00)
                    {
                        cout << "\nGAME OVER!\n";
                        cout << "Your selection of coins was less than $1.00.\n";
                    }
                    else if (coinsTotal > 1.00)
                    {
                        cout << "\nGAME OVER!\n";
                        cout << "Your selection of coins was more than $1.00.\n";
                    }
                }
            }
        }
    }

    return 0;
}

Upvotes: 0

Views: 161

Answers (3)

Chris
Chris

Reputation: 36611

Early exit

If nothing else follows, you can use the control flow mechanism of a return to avoid the nested conditionals. The early exit means the remaining code in the function is never executed.

E.g.

int main()
{
    int pennies, nickels, dimes, quarters;
    double penniesTotal, nickelsTotal, dimesTotal, quartersTotal, coinsTotal;


    cout << "Enter a quantity of coins needed to make EXACTLY one dollar.\n";

    cout << "\nEnter the amount of pennies: ";
    cin >> pennies;
    
    // ensures user enters amount of pennies greater than or equal to zero
    if (pennies < 0) {
        cout << "\nAmount of pennies must be greater than or equal to zero!";
        return 0;
    }
    
    penniesTotal = pennies * 0.01;

    cout << "\nEnter the amount of nickels: ";
    cin >> nickels;

    // ensures user enters amount of nickels greater than or equal to zero
    if (nickels < 0) {
        cout << "\nAmount of nickels must be greater than or equal to zero!";
        return 0;
    }
    
    nickelsTotal = nickels * 0.05;
    cout << "\nEnter the amount of dimes: ";
    cin >> dimes;

    // ensures user enters amount of dimes greater than or equal to zero
    if (dimes < 0) {
        cout << "\nAmount of dimes must be greater than or equal to zero!";
        return 0;
    }
   
    dimesTotal = dimes * 0.10;
    cout << "\nEnter the amount of quarters: ";
    cin >> quarters;
    // ensures user enter amount of quarters greater than or equal to zero
    if (quarters < 0) {
        cout << "\nAmount of quarters must be greater than or equal to zero!";
        return 0;

    quartersTotal = quarters * 0.25;
    // adds all coins together
    coinsTotal = penniesTotal + nickelsTotal + dimesTotal + quartersTotal;

    // identifies if coins are less than, greater than, or equal to $1.00
    if (coinsTotal == 1.00) 
    {
        cout << "\nCONGRATULATIONS!\n" <<  "Your selection of coins adds up to $1.00.\n";
    }
    else if (coinsTotal < 1.00)
    {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was less than $1.00.\n";
    }
    else if (coinsTotal > 1.00)
    {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was more than $1.00.\n";
    }
            
    return 0;
}

Conditionals

Consider also that in your final conditional, the last test is extraneous. If neither previous test has been true, coinsTotal must be greater than 1.00.

    if (coinsTotal == 1.00) {
        cout << "\nCONGRATULATIONS!\n" <<  "Your selection of coins adds up to $1.00.\n";
    }
    else if (coinsTotal < 1.00) {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was less than $1.00.\n";
    }
    else {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was more than $1.00.\n";
    }

Don't Repeat Yourself

It is possible to greatly reduce the duplication by using a vector of structs containing coin-specific data.

#include <iostream>
#include <string>
#include <vector>

struct coin_data {
    std::string name;
    double value;
};

int main() {
    using std::cout;
    using std::cin;

    std::vector<coin_data> coins = {
        {"pennies",  0.01},
        {"nickels",  0.05},
        {"dimes",    0.10},
        {"quarters", 0.25}
    };

    double total_value = 0.0;

    for (auto &coin : coins) {
        cout << "Enter the number of " << coin.name << ": ";

        int count;
        cin >> count;

        if (count < 0.0) {
            cout << "Amount of " << coin.name << " must be greater than or equal to zero.\n";
            return 0;
        }

        total_value += count * coin.value;
    }

    if (total_value == 1.00) {
        cout << "\nCONGRATULATIONS!\n" <<  "Your selection of coins adds up to $1.00.\n";
    }
    else if (total_value < 1.00) {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was less than $1.00.\n";
    }
    else {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was more than $1.00.\n";
    }

    return 0;
}

Or you can avail yourself of the standard library, and use a std::vector of std::pair. as noted, this is also an opportunity to fix the math to use integers rather than floating point numbers for money math.

#include <iostream>
#include <string>
#include <vector>
#include <utility>

int main() {
    using std::cout;
    using std::cin;
    using coin_data = std::pair<std::string, int>;

    std::vector<coin_data> coins = {
        {"pennies",   1},
        {"nickels",   5},
        {"dimes",    10},
        {"quarters", 25}
    };

    int total_value = 0;

    for (auto &[name, value] : coins) {
        cout << "Enter the number of " << name << ": ";

        int count;
        cin >> count;

        if (count < 0) {
            cout << "Amount of " << name << " must be greater than or equal to zero.\n";
            return 0;
        }

        total_value += count * value;
    }

    if (total_value == 100) {
        cout << "\nCONGRATULATIONS!\n" <<  "Your selection of coins adds up to $1.00.\n";
    }
    else if (total_value < 100) {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was less than $1.00.\n";
    }
    else {
        cout << "\nGAME OVER!\n";
        cout << "Your selection of coins was more than $1.00.\n";
    }

    return 0;
}

Upvotes: 10

selbie
selbie

Reputation: 104559

I can name that tune in two notes. Or more precisely. Keep track of the current "state" as an index and use that as an index into a table to fill which variable with the user's typed amount. Also used to print the current denomination. And avoid floating point, the root of all evil, as well.

int main()
{
    int pennies, nickels, dimes, quarters;
    std::string coinTable[] = {"pennies", "nickels", "dimes", "quarters", "done"};
    int* counts[] = { &pennies, &nickels, &dimes, &quarters, NULL };
    int coinIndex = 0;

    // coinIndex == 4 -> completed
    // coinIndex == 5 -> error

    cout << "Enter a quantity of coins needed to make EXACTLY one dollar.\n";

    while (coinIndex < 4)
    {
        int coins = -1;
        cout << "\nEnter the amount of " << coinTable[coinIndex] << ": ";
        cin >> coins;
        if (coins < 0)
        {
            cout << "\nAmount of " << coinTable[coinIndex] << " must be greater than or equal to zero!\n";
            coinIndex = 5; // error state
        }
        else
        {
            int* ptr = counts[coinIndex];
            *ptr = coins;
            coinIndex++;
        }
    }

    if (coinIndex == 4)
    {
        int total = pennies + nickels * 5 + dimes * 10 + quarters * 25;
        if (total != 100)
        {
            cout << "\nGAME OVER!\nYour selection was " << ((total < 100) ?"less":"more") << " than a dollar!";
        }
        else
        {
            cout << "\nCongratulations!\nYou got it right\n";
        }
    }
    return 0;
}

Upvotes: 0

Gabe Sechan
Gabe Sechan

Reputation: 93668

You can make a function for a lot of the boilerplate:

int getCoinCount(string coinName) {
    int coins;
    cout << "\nEnter the amount of "<<coinName<<":";
    cin >> coins;
    // ensures user enters amount of coins greater than or equal to zero
    if (coins < 0)
        cout << "\nAmount of "<<coinName<<" must be greater than or equal to zero!";
    return coins
}

int main() {
    int pennies = getCoinCount("pennies")
    if( pennies > 0) {
        int nickles = getCoinCount("nickles")
    ...

Combine with Chris's suggestion of early returns on errors and you have a lot clearer code with less replication. If you can combine with a reprompt (just loop asking for another number if the number is illegal rather than exiting) you can have a really clear main:

int main() {
    int pennies= getCoinCount("pennies")
    int nickles = getCoinCount("nickles")
    ...
    int totalInCents = calculateTotal(pennies, nickles, dimes, quarters)
    printGameResult(totalInCents)  
}

Upvotes: 4

Related Questions