1

I'm needing a little help, this program is meant to calculate and output the body weight of users vs their body weight on planets in our solar system.

When I try to use a switch statement for this program, the entire statement is marked as error specifically 'Illegal case error' and 'case label may only be used within a switch' errors .I have tried comparing my statement with others in my textbook but can find no difference. Please tell me how I can fix this.

#include <cctype>
#include <iostream>
#include <cmath>


using namespace std;

double weight;
double planet_weight;
string planet;
double weightonplanet = 0;

enum planet_names{Mercury,Venus,Earth,Moon,Mars,Jupiter,Saturn,Uranus,Neptune,Pluto};



int main()
{
    cout << "********************************************************************" << endl;
    cout << endl;
    cout << "Enter the name of a planet from the following options:" << endl;
    cout << "(Mercury,Venus,Earth,Moon, Mars,Jupiter,Saturn,Uranus,Neptune,Pluto)" << endl;
    cout << endl;
    cout << "********************************************************************" << endl;
    cin >> planet;

    cout << endl;
    cout << endl;
    cout << "Please enter your current weight (ex:205)" << endl;
    cin >> weight;
    cout << endl;

    cout << "You have entered " << planet << "." << endl;
    cout << "You currently weigh " << weight << "lbs." << endl;
    cout << "Your weigh on " << planet << "is " << weightonplanet << " ." << endl;

    while (true)
    {
        switch (string planet);
        {
        case Mercury:
            weightonplanet = weight * 0.4155;
            break;
        case Venus:
            weightonplanet = weight * 0.8975;
            break;
        case Earth:
            weightonplanet = weight * 1.0;
            break;
        case Moon:
            weightonplanet = weight * 0.166;
            break;
        case Mars:
            weightonplanet = weight * 0.3507;
            break;
        case Jupiter:
            weightonplanet = weight * 2.5374;
            break;
        case Saturn:
            weightonplanet = weight * 1.0677;
            break;
        case Uranus:
            weightonplanet = weight * 0.8947;
            break;
        case Neptune:
            weightonplanet = weight * 1.1794;
            break;
        case Pluto :
            weightonplanet = weight * 0.899;
            break;
        }
    }

        return weightonplanet;

2 Answers2

1

Problem 1: Bogus semicolon.

switch (string planet);
                      ^
                      remove me!

Problem 2: Can't switch on a string

The why is covered here: Why the switch statement cannot be applied on strings?

Solution

So what can we do? We can have a chain of if-else-if statements comparing strings. Sounds ugly but for short lists, this is probably the fastest approach. Note: If you go this route, you can directly compare std::strings, so there is no need for strcmp.

if (planet == "Mercury")
{
    weightonplanet = weight * 0.4155;
}
if (planet == "Venus")
{
    weightonplanet = weight * 0.8975;
}
...

We can also map the planet name to the enum and then switch on the enum. But if we're going to do that, why not eliminate the enum and the switch and map the planet name directly to the planet's gravity?

To demonstrate this I'll use std::map from the C++ Standard Library.

#include <iostream>
#include <string> // added to get std::string. Sometimes you get it free from
                  // iostream, but you can't count on this, so leaving string 
                  // out could be leaving a boobytrap for someone in the future
                  // If you use it, include it.
#include <map> // added to get std::map

using namespace std; // often dangerous. Use with caution

int main()
{
    // No need for these variables to be global. Enclose them in main's scope
    double weight;
    string planet;
    // removed a couple variables because they're not needed anymore

    // you can chain <<s into one big statement. No need to line them up all nice and purty
    // I just find it easier to read. Easier to read is easier to debug and maintain,
    // so it worth the time spent. Your mileage may vary.
    cout << "********************************************************************" << endl
         << endl
         << "Enter the name of a planet from the following options:" << endl
         << "(Mercury,Venus,Earth,Moon, Mars,Jupiter,Saturn,Uranus,Neptune,Pluto)" << endl
         << endl
         << "********************************************************************" << endl;
    cin >> planet;

    cout << endl
         << endl
         << "Please enter your current weight (ex:205)" << endl;
    cin >> weight;

    // can't switch on a string so here I'm mapping planet names to gravity
    map<string, double> weightmap =
    {
      { "Mercury", 0.4155 },
      { "Venus", 0.8975 },
      { "Earth", 1.0 },
      { "Moon", 0.166 }, // not a planet.
      { "Mars", 0.3507 },
      { "Jupiter", 2.5374 },
      { "Saturn", 1.0677 },
      { "Uranus", 0.8947 },
      { "Neptune", 1.1794 },
      { "Pluto", 0.899 } // not a planet.
    };

    // so now here we just look up the planet name in the map, and get gravity
    // one multiplication later, we're done!
    cout << endl
         << "You have entered " << planet << "." << endl
         << "You currently weigh " << weight << "lbs." << endl
         << "Your weight on " << planet << "is " << weight * weightmap[planet] << " ." << endl;
}

There are a few problems here. "Saturn" is not the same as "saturn". You may want to convert the user's input to lower or upper case and only test that one case.

If the user inputs a name that is not in the map, the map will create a new entry for that planet and initialize it to zero. So as far as this program is concerned, "Iscandar" has zero gravitational force. If you want to trap planets not in the map, use std::map::find. If the input is not found, ask the user to provide another input. Or mock them mercilessly and exit. Your call.

A quick note about map creating entries for you. This can be extremely useful, frequency counters of sparse items for example, but if the program will run for a long time take care that you don't fill up an ungodly amount of memory with typos.

Finally, a quick note on using namespace std;: Why is "using namespace std;" considered bad practice?

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Addendum: `endl` is more than just a new line. It also writes ("flushes") the stream buffer into the underlying media. This can be a very slow operation, so you want to do it as infrequently as possible. Prefer to use a newline character `'\n'` and save `endl` for when you need to get the buffered data out as soon as possible. – user4581301 Apr 13 '20 at 05:05
  • And, at contrario, flushing avoids some debugging issue with beginners. – Jarod42 Apr 13 '20 at 08:08
-1

after user input you must set a countable variable(int, enum, enum class, ...) for each string and use this variable to process on user input and i think it's bad idea.

in this case you can use 'if - else' statements. for example

if(!strcmp(planet, "Mercury"))
{
    //do your job
}
else if(!strcmp(planet, "Mars")
.
.
.
MH Alikhani
  • 110
  • 7
  • 1
    Got a bug here. The asker is using `std::string` and `strcmp` doesn't accept `std::string`s. Fortunately you can directly compare `std::string`s with other `std::string`s or null-terminated character arrays with the `==` operator. – user4581301 Apr 13 '20 at 04:39