enumeration/ illegal switch statement error in C++ - c++

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;

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?

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

Related

Doing while loop properly until "0" input to stop the loop?

I need help. I'm currently learning C++ programming and I'm still at the beginner level. I'm still figuring out how to make the while loop working. My idea is when inserting the correct code input, the switch statement choose the right case statement and loop back to insert another input until 0 inserted to stop the loop and calculate for the final output in main() constructor.
I know I have few kinks to fix soon but I'm still struggling to figure out this particular part.
#include <stdio.h>
#include <iostream>
#include <iomanip>
using namespace std;
double sst = 0.06, total = 0, grandTotal, price, discount, newPrice, totalSST;
int quantity, count, code;
string name, ech;
void item001(){
name = "Rice (5kg)";
price = 11.5;
discount = 0;
}
void item002(){
name = "Rice (10kg)";
price = 25.9;
discount = 0;
}
void item003(){
name = "Sugar (1kg)";
price = 2.95;
discount = 0;
}
void item_cal(){
cout << "Please enter the quantity of the item: ";
cin >> quantity;
newPrice = (price + (discount * price)) * quantity;
cout << "\nItem: " << name << " || Quantity: " << quantity << " || Price: RM" << newPrice << endl;
}
void input(){
cout << "Welcome SA Mart\n" << "Please insert the code. Press 0 to stop: ";
while (code != 0){
cin >> code;
switch (code){
case 001:
item001();
item_cal();
break;
case 002:
item002();
item_cal();
break;
case 003:
item003();
item_cal();
break;
default:
cout << "\nWrong code" << endl;;
break;
total += newPrice;
}
}
}
int main(){
input();
totalSST = total * sst;
grandTotal = total + totalSST;
cout << fixed << setprecision(2);
cout << "Total: RM" << total << " ||SST: RM" << totalSST << " || Grand Total: RM" << grandTotal << endl;
return 0;
}
The only functional issue I see in your code is that there is a chance that the code variable will initialize to 0 (depends on the compiler/randomness). If that happens, your input method will return before it enters the loop. Other than that it looks like it will work. Of course, programming is not just the art of "making it work," style and readability are important too. In general, you want to confine variables to the smallest scope in which they are referenced. 'code' should not be a global variable, it should live in the input method. As for the loop, there are several ways it could be implemented: a "while(true)" loop could be used, in which case the variable may be defined inside the loop; on the other hand a "do while" would guarantee one loop runs (perhaps that would be a good fit here), but the variable must live outside of the loop, at least int the scope of conditional check. The way you choose is often a matter of style. Below, I use a "while(true)."
In programming, readability matters (a lot). I think this program would be easier to read if the data were broken up into a few structs, perhaps "Bill," and "Food." Another thing to consider is how to broaden the usage of your program, without introducing significant complexity. For example, it could work for any grocery store (any set of food items/prices). This is often a matter of determining an appropriate set of parameters to feed your program.
To do these things you might write something like this:
#pragma once
#include <string>
#include <map>
using namespace std;
namespace market {
const double& sst = 0.06;
struct Bill {
double total = 0;
double totalSST = 0;
double grandTotal = 0;
};
struct Food {
const char* name;
double price;
double discount;
Food(const char* name, double price, double discount = 0)
: name(name), price(price), discount(discount) {}
double result_price() const {
return price - price * discount;
}
};
struct GroceryStore {
const char* name;
std::map<int, Food> inventory;
GroceryStore(const char* name, std::map<int, Food> inventory)
: name(name), inventory(inventory) { }
};
void shop(const GroceryStore& store, Bill& bill, bool show_menu = false, int exit_code = 0) {
// check error conditions
if (store.inventory.find(exit_code) != store.inventory.end()) {
// that's the 'exit_code' code silly!
cout << "Bad store. Come back another time." << endl;
return;
}
cout << "Welcome to " << store.name << endl;
if (show_menu) {
cout << "The following items are available for purchase:" << endl;
for (auto p : store.inventory) {
cout << "\t" << p.first << ") " << p.second.name << "(" << p.second.result_price() << endl;
}
}
cout << "Enter the product code of the item you wish to purchase:";
int code;
cin >> code;
while (true) {
auto food_it = store.inventory.find(code);
if (food_it == store.inventory.end()) {
cout << "Thanks for stopping by." << endl;;
break;
}
cout << "Please enter the quantity of the item: ";
uint32_t quantity;
cin >> quantity;
auto& food = food_it->second;
auto disc_price = food.price - (food.discount * food.price);
bill.total += disc_price * quantity;
cout << "\nItem: " << food.name << " || Quantity: " << quantity << " || Price: RM" << disc_price << endl;
cout << "Would you like anything else? Enter the product code, or press " << exit_code << " to proceed to check-out." << endl;
cin >> code;
}
}
void ring_up(Bill& bill) {
bill.totalSST = bill.total * sst;
bill.grandTotal = bill.total + bill.totalSST;
}
void run() {
int code = 1;
GroceryStore store("SMart", {
{ code++, Food("Rice (5kg)", 11.5, 0) },
{ code++, Food("Rice (10kg)", 25.9) },
{ code, Food("Sugar (1kg)", 2.95, 0) }
});
Bill bill;
shop(store, bill, true);
ring_up(bill);
cout << "Total: RM" << bill.total << " ||SST: RM" << bill.totalSST << " || Grand Total: RM" << bill.grandTotal << endl;
}
}
Firstly there is a bug in input when u will input 0 then also it won't break while loop as code that is checked contains the previous value.
for example:
input is
3
0
but according to your code when the code will run the second time and while condition is checked code still contains 3 as value and code will run one more time
Try initialising code to some value, for example, -1. I'm not really sure but I think for global int variables, they initialise int variables to 0. So your first loop doesn't run. Or another way to do it is using do while loops instead of while loop.
do {
cin >> code;
switch (code){
case 001:
item001();
item_cal();
break;
case 002:
item002();
item_cal();
break;
case 003:
item003();
item_cal();
break;
default:
cout << "\nWrong code" << endl;;
break;
total += newPrice;
} while (code != 0);
}
This makes sure that the loop will run at least once, making code initialised.
Hope it helps you! Have fun programming!

How to call user defined functions in C++?

Below you will find my dismal attempt to create a user defined function. I am trying to do an assignment that calculates the area and cost of installing carpet for various shapes. I am also suppose to keep a running total of them. In addition the assignment requires that I use a used defined function. Right now all it does is accept the input of 1 and ask "What is the length of the side: ". It then loops back to the selection menu. It does not calculate a total much less keep track of the total. What am I doing wrong in creating the user defined function and how can I incorporate it to keep a running total till they exit?
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
using namespace std;
void square(double);
const double UNIT_PRICE = 2.59;
const double LABOR_COST = 32.5;
const double PIE = 3.14;
const double TAX = .0825;
int main() {
int selection;
int sqrSide = 0;
// declare and initialize the variables for the shape
int sqrTot = 0;
do {
// get input from user as to what they want to do
cout << "Carpet Area Shape" << endl;
cout << "1. Square" << endl;
cout << "2. Rectangle" << endl;
cout << "3. Circle" << endl;
cout << "4. Triangle" << endl;
cout << "5. Done" << endl;
cout << "Type a number to continue: ";
cin >> selection;
cout << endl;
// loop through the solutions based on the user's selection
switch (selection) {
case 1:
cout << "What is the length of the side: ";
cin >> sqrSide;
square(sqrSide);
if (sqrTot > 0) {
cout << "Shape: Square" << endl;
cout << "Side: " << sqrSide << endl;
cout << "Area: " << sqrTot << endl;
}
cout << endl;
system("pause");
break;
case 2:
case 3:
case 4:
case 5: // exit
system("cls");
break;
default:
"You have made an invalid selection. Please choose a number from the "
"list.";
cout << endl;
}
// loop through if the user is still making a valid selection
} while (selection != 5);
system("pause");
return 0;
}
void square(double) {
double sqrSide = 0;
double sqrTot = 0;
double sqrArea;
sqrArea = sqrSide * 4;
// get the total area and store it as a variable
sqrTot += sqrArea;
if (sqrTot > 0) {
cout << "Shape: Square" << endl;
cout << "Side: " << sqrSide << endl;
cout << "Area: " << sqrTot << endl;
}
}
When you declare the prototype of the function you can omit the parameter but in the implementation you must place it.
change:
void square(double)
{
double sqrSide = 0;
double sqrTot = 0;
double sqrArea;
sqrArea = sqrSide * 4;
//get the total area and store it as a variable
sqrTot += sqrArea;
if (sqrTot > 0) {
cout << "Shape: Square" << endl;
cout << "Side: " << sqrSide << endl;
cout << "Area: " << sqrTot << endl;
}
}
to:
void square(double sqrSide)
{
double sqrTot = 0;
double sqrArea;
sqrArea = sqrSide * 4;
//get the total area and store it as a variable
sqrTot += sqrArea;
if (sqrTot > 0) {
cout << "Shape: Square" << endl;
cout << "Side: " << sqrSide << endl;
cout << "Area: " << sqrTot << endl;
}
}
and also change:
case 1:
cout << "What is the length of the side: ";
cin >> sqrSide;
square(sqrSide);
if (sqrTot > 0) {
cout << "Shape: Square" << endl;
cout << "Side: " << sqrSide << endl;
cout << "Area: " << sqrTot << endl;
}
cout << endl;
system("pause");
break;
to:
case 1:
cout << "What is the length of the side: ";
cin >> sqrSide;
square(sqrSide);
system("pause");
break;
As mentioned by πάνταῥεῖ in a comment, it seems that you've a few misconceptions regarding scope of variables, about parameters and about return values. Let's see if we can't dispel some of those.
First of all, lets talk about scope. When we declare a variable inside a block delimited with { and }, the variable only exists inside that block. Code that follows the block cannot access the variable.
So, this is okay:
int a = 3;
int b = 2;
int c = a*b;
But, this is not, since the values of a and b are no longer available:
{
int a = 3;
int b = 2;
}
int c = a*b;
Next, lets talk about parameters. These are the inputs to functions which the function will use in order to complete its task. While their name is irrelevant and essentially meaningless, it will certainly help you and others of you give them meaningful names. Some programming languages and indeed, students of some disciplines don't follow this maxim and can produce code that's harder to follow than it need be. The implementation of Basic found in 20 year old Texas Instruments calculators and physicists, I'm looking at you!
Consider the following functions, (whose bodies I've ommitted for brevity):
double calcArea(double a)
{
...
}
double calcArea(double b)
{
...
}
They both suck. What's a stand for, how about b?
A far better pair might resemble:
double calcArea(double radius)
{
...
}
double calcArea(double sideLenOfSquare)
{
...
}
Lastly, lets talk about return values. In each of the 4 preceding functions, the declaration begins with double. This means that we can expect to get back a value of type double from the function. However, this is just coding - there's no magic and as such, we need to actually let the compiler know what this value will be. Extending the two previous functions, we might come up with some something like the following:
double calcArea(double radius)
{
return 3.1415926535 * (radius * radius);
}
double calcArea(double sideLenOfSquare)
{
return sideLenOfSquare * sideLenOfSquare;
}
Now as it turns out - even these two simple functions are not all they've cracked-up to be. Namely, the first function uses a constant - π (Pi or 3.141....) This already exists (and with far better precision than I've used) in the math.h header file. If this file is included, we then have access to the #defined constant, M_PI.
Next, both of these functions have the same name and take the same number of parameters of identical type. The compiler can't possibly know which one you'd like to invoke. At a minimum, they should have different names. Perhaps something like calcCircleArea and calcSquareArea. Now, the compiler knows which function you're referring to and will happily compile this part of the code. Errors may exist elsewhere, but these are a different matter.
A little research on function overloading will provide resources that can explain the problem and solution to functions with the same name far better than I am both able and inclined to try. :)

Where am I going wrong with Enums & Switchblocks

I am learning C++ as part of my course at Uni. I am not all that experienced in c++ but I have searched for possible solutions for several hours and tested hundreds of variations of code and I still cannot get this working. I believe that my use of Enums must be fundamentally wrong - I have never got them working as I intended. For this task we had to use Enums and a switch statement.
#include <iostream>
using namespace std;
enum roomType { Deluxe = 250, Twin = 150, Single = 110};
int temp;
int total;
int input = 1; int yes = 1; int no = 0;
void GetInput()
{
cin >> input;
temp = temp*input;
}
int main()
{
if (input != 0)
{
cout << "\nRoom Price Code\n------------------------------------\nDeluxe Room " << "\x9C" << "200 D\nTwin Room " << "\x9C" << "150 T\nSingle " << "\x9C" << "110 S\n\n";
cout << "Enter room type:";
GetInput();
switch (input) {
case Deluxe:
temp = Deluxe;
break;
case Twin:
temp = Twin;
break;
case Single:
temp = Single;
break;
default:
//prevents infinite loop bug
system("pause");
cout << "Entry not recognized";
main();
break;
}
cout << "\nEnter number of rooms:";
GetInput();
cout << "\nEnter number of nights:";
GetInput();
total = total + temp;
cout << "\n\x9C" << total << "\n";
cout << "More rooms? yes/no: ";
cin >> input;
main();
}
cout << "Discount? yes/no: ";
GetInput();
if (input = 1)
{
total = ((total / 100) * 75);
cout << "\n\x9C" << total << "\n";
}
cout << "your total is "<<"\x9C" << total;
system("pause");
system("cls");
return 0;
}
If the User enters a room type for instance Deluxe, the case statement always goes to default, then without the system("pause"); would proceed to get stuck in a loop.
For some reason the program seems to ignore all the cin >> input;'s after the first one. I know that it is this that is causing the looping. I have tried switching cin>> out for a getline(cin,input)alternative but that doesn't seem to work either.
Just compiled your code. You are not doing anything wrong for Delux. Just silly error that enum value is 250 and you are displaying 200. So while running, you are entering 200 and it goes to default.
Coming to second question that why program runs only once, its because you want it that way. The check if (input != 0) checks for input type as integer value. You might be entering 'yes' in command line and not doing any error checks. Try entering integer value.
PS: In future, please paste the code in question itself.
NOTE: This does not answer the users question directly; I have done that above. This is an example that is based off of one of the replies from the user and is here to demonstrate the uses of enumerations and enumerated types so that they may be able to have an easier and better understanding of them.
Here are two function prototypes that would do the same thing one uses enumerations while the other doesn't.
enum ProductType {
HARDWARE = 1,
TOOLS,
APPLIANCES,
FURNITURE,
LAWN_AND_GARDEN,
PAINT
};
// This Version Doesn't Use An Enumerated Value And Takes In An Unsigned Int
float calculateProductTotalCost( unsigned int productType, float costOfProduct, unsigned int numberOfItems );
float calculateProductTotalCost( ProductType type, float costOfProduct, unsigned int numberOfItems );
someOtherFunction() { // Could be main()
// This function has a magic number to represent the product type
calcluateProductTotalCost( 3, 1499.99f, 2 );
// This version uses the enumeration with the scope resolution operator
// to allow the calling of this function to be easier to read.
calculateProductTotalCost( ProductType::PAINT, 23.50f, 150 );
// Although I did not show any implementation for these functions
// since that is irrelevant, the importance of the two is that in
// practice these methods would be the same and perform the same
// exact calculation and operation. It is just more readable for
// another human to see your code when they have to work on it
// sometime in the future and you are not there to explain what you
// did and why you did it. It can even be a help for yourself if
// you go back to code that you have written that you have not seen
// in a few months or years. Then just by reading the Wording
// of the Enumeration you know that this value represents this specific
// object.
}
Here is another example
SoundSource {
CLAP = 1,
BANG,
GUN_SHOT,
THUNDER_BOLT,
LAUGHTER,
SCREAM,
};
bool playSound( unsigned int, bool bLoop );
bool playSound( SoundSource, bool bLoop );
someFunction() {
// Which group of function calls looks better and is easier to understand; Group A or Group B?
// Group A
playSound( 6, false );
playSound( 4, true );
playSound( 3, false );
// Group B
playSound( SoundSource::THUNDER_BOLT, true );
playSound( SoundSource::SCREAM, false );
playSound( SoundSource::LAUGH, true );
}
I hope this helps you to understand the uses of Enums; they are great for a few different things, good for switch case statements, and for allowing different data types that are usually passed in by an ID value usually an unsigned to also be represented by words that are an enumerated value. If you notice it is good practice to name all of your Values within the Enum in ALL_CAPS separating each word by an underscore; but this is also just preference, but most people will recognize this as an enum when they see all caps.
You have a lot of errors in this code; I structured the enum to represent an enumerated value for a switch selection, the prices are assigned in the case statements. Many times are you making a call to main(); I've never seen this done in practice! I can not say that it is invalid or illegal, but I've never seen it! I chose appropriate variable types for the right kind of concept or idea such as the cost of something being a float, when you ask user for input if there are more rooms or not or if there is a discount or not I used a bool type. Values that you know that will not be negative I used unsigned. I removed all global variables (usually bad practice). I fixed some formatting for easier readability.
Here is what I did and I have some comments to explain the changes I've made; other changes you will need to think about what I have done.
#include <iostream>
// using namespace std; // Bad Practice
enum RoomType {
NONE = 0, // NONE For Default Value - No Room Type Selected
DELUXE,
TWIN,
SINGLE,
LAST // MUST BE LAST!
};
/*void GetInput() { // Function Not Really Required In This Simple Application
cin >> input;
temp = temp*input;
}*/
int main() {
while ( true ) {
float totalCost = 0; // Renamed Variable For Better Readability
int input = 0; // Initialized To 0, We Do Not Know What The User Will Choice
std::cout << std::endl << "Room Price Code" << std::endl
<< "------------------------------------" << std::endl
<< "Deluxe Room " << "\x9C" << "250 D" << std::endl
<< "Twin Room " << "\x9C" << "150 T" << std::endl
<< "Single " << "\x9C" << "110 S" << std::endl << std::endl;
std::cout << "Please Make A Selection:" << std::endl
<< "1 - Deluxe" << std::endl
<< "2 - Twin" << std::endl
<< "3 - Single" << std::endl << std::endl;
std::cin >> input;
// You Never Declare Variable Type Of RoomType
RoomType type = static_cast<RoomType>( input ); // Cast input to RoomType
float costOfRoom = 0.0f;
switch (type) {
case NONE: {
costOfRoom = 0.0f;
break;
}
case DELUXE: {
costOfRoom = 250.0f;
break;
}
case TWIN: {
costOfRoom = 150.0f;
break;
}
case SINGLE: {
costOfRoom = 110.0f;
break;
}
default: {
std::cout << "Entry not recognized";
//main(); wrong
break;
}
} // Switch
unsigned numRooms = 0;
unsigned numNights = 0;
std::cout << std::endl << "Enter number of rooms:";
std::cin >> numRooms;
std::cout << std::endl << "Enter number of nights:";
std::cin >> numNights;
totalCost = costOfRoom * numNights * numRooms;
std::cout << "\n\x9C" << totalCost << "\n";
bool moreRooms = false;
bool hasDiscount = false;
input = 0;
std::cout << "More rooms? 1 for yes - 0 for no: ";
std::cin >> moreRooms;
if ( moreRooms ) {
std::cout << "Please Enter Number Of Rooms. ";
std::cin >> input;
totalCost += (costOfRoom * numNights * input);
}
// main(); // Wrong!
std::cout << "Discount? 1 for yes - 0 for no: ";
std::cin >> hasDiscount;
if ( hasDiscount ) {
totalCost = ((totalCost / 100) * 75);
std::cout << std::endl << "\x9C" << totalCost << std::endl;
}
std::cout << "Your total is " <<"\x9C" << totalCost << std::endl;
bool runAgain = false;
std::cout << std::endl << "Would you like to contine? 1 - yes - 0 for no:";
std::cin >> runAgain;
if ( !runAgain ) {
break;
}
} // while
system("pause");
system("cls");
return 0;
} // main

C++ Variables Losing Assignment Inside "if" Loop

So this is a very simple problem I'm sure, but I'm just starting out.
In the program, there is simple input validation. If inputed is entered properly, no issues.
The problem is, when testing the program with an error, like entering a zero or negative number, all the variables are blank (i.e., strings become blank and numbers become zero) in the output.
Thanks ahead of time for the help and insight.
// This menu driven program determines the time sound will take to travel through
// gas, liquid, and solid, given a distance from a user.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
// constants
const double AIR_SPEED_RATE_PER_SECOND_SOUND = 1100.0, //in feet per second
WATER_SPEED_RATE_PER_SECOND_SOUND = 4900.0, // in feet per second
STEEL_SPEED_RATE_PER_SECOND_SOUND = 16400.0; // in feet per second
// Program defined variables
double Time_To_Travel = 0.0; // in seconds
string Medium;
// User defined variables
double distance_of_travel; //in feet
int menu_selection;
//Display a menu for mediums of sound conduction.
cout << "Sound travels at different speeds through air, water, and steel." << endl;
cout << "\nThis program will calculate the time it takes, in feet per second, for " \
"sound to travel a given distance." << endl;
cout << "Please select a number choice below:\n\n1. Air\n2. Water\n3. Steel " << endl;
//Get input from user.
cout << "\nEnter Selection: ";
cin >> menu_selection;
cout << "\nEnter distance in feet the sound will travel: ";
cin >> distance_of_travel;
// Input validate selection is on the menu
if (menu_selection >= 1 && menu_selection <= 3)
{
if (distance_of_travel > 0.0) // input validation distance is positive
{
switch (menu_selection) // calculate the time of travel based on user input
{
case 1: Medium = "air";
Time_To_Travel = distance_of_travel / AIR_SPEED_RATE_PER_SECOND_SOUND;
break;
case 2: Medium = "water";
Time_To_Travel = distance_of_travel / WATER_SPEED_RATE_PER_SECOND_SOUND;
break;
case 3: Medium = "steel";
Time_To_Travel = distance_of_travel / STEEL_SPEED_RATE_PER_SECOND_SOUND;
break;
}
}
else
{
cout << "\nPlease enter a distance greater than zero: ";
cin >> distance_of_travel;
}
}
else
{
cout << "\nMenu selection is not 1, 2, or 3.\n\nPlease correctly enter a number 1 through 3: ";
cin >> menu_selection;
}
// Format to four decimal places and display the time sound takes to travel given distance.
cout << fixed << showpoint << setprecision(4);
cout << "Sound would take " << Time_To_Travel << " seconds to travel given distance of " << distance_of_travel << " feet in " << Medium << "." << endl;;
return 0;
}
An if statement is a simple branch, not a loop. At the end of the if, execution continues past the end of the block.
if (menu_selection >= 1 && menu_selection <= 3)
This, when false, will skip the meat of your program and jump to your code that handles invalid input.
else
{
cout << "\nMenu selection is not 1, 2, or 3.\n\nPlease correctly enter a number 1 through 3: ";
cin >> menu_selection;
}
After you input menu_selection again, control flows to
cout << fixed << showpoint << setprecision(4);
cout << "Sound would take " << Time_To_Travel << " seconds to travel given distance of " << distance_of_travel << " feet in " << Medium << "." << endl;;
return 0;
The new input is never acted on, and the untouched values are printed. Replace the initial if with a do {...} while(condition); loop that wraps the user input. Once the input is satisfactory, you can then proceed to the core of the program.
bool is_good;
do
{
is_good = false;
cout << "\nEnter Selection: ";
cin >> menu_selection;
cout << "\nEnter distance in feet the sound will travel: ";
cin >> distance_of_travel;
if (menu_selection < 1 || menu_selection > 3 || distance_of_travel < 0)
cout << "error message here";
else
is_good = true;
} while (!is_good);
You can handle zero, negative number, or all possible inputs that are not defined in your case block by adding default block to your switch statement. Then your code will look like something like this.
switch (menu_selection) // calculate the time of travel based on user input
{
case 1: Medium = "air";
Time_To_Travel = distance_of_travel / AIR_SPEED_RATE_PER_SECOND_SOUND;
break;
case 2: Medium = "water";
Time_To_Travel = distance_of_travel / WATER_SPEED_RATE_PER_SECOND_SOUND;
break;
case 3: Medium = "steel";
Time_To_Travel = distance_of_travel / STEEL_SPEED_RATE_PER_SECOND_SOUND;
break;
default:
// handle zero, negative numbers and so on.
break;
}
Reference: http://www.tutorialspoint.com/cplusplus/cpp_switch_statement.htm

On finding vowels and capitals char in the beginning of a string?

I've been making a little memory game as an exercise from a textbook I'm doing. It's called Grandma's trunk and it works by in one turn you found an item in the trunk and the next turn you say you found the previous item and the newest item on this turn...I think.
Mostly it's an exercise on using functions, which I think I've gotten down pretty well. But my output is completely wrong. I've believe I've located the problem in one function where I'm supposed to analyze the first character and decided if it needs an AN or A or THE before the string. There might be a problem with the random function I'm using to throw in predefined items from a small database. The int main() function is supposed to be relatively complete, this is just an exercise to master functions...which I, sorta? Would rather call it novice experience.
I thought that perhaps I was running into the getline bug where it couts a blank line, and from my understanding, is fixed by cin.ignore(); but all that did was force me to press enter twice when I enter data. Which...I sort of like. Perhaps I'm using gizmos like isupper and .at() wrong? I tried using find_first_of but it didn't really change anything.
output calling the storage trunk and the owner grandma and just using word1 word2 word3... wordn....as items found leaves me with the output.
In grandma trunk you've found a
and an ord3 word1.
it completely muddles up the output. I'm starting to think that the int main() body I was given wasn't exactly stellar. But I can't be 100% confident in my article function. Any help would just be incredible. I've been struggling using this among many books and advice from a buddy to teach myself a little about programming. It's been a rather huge headache.
program itself
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
using namespace std;
string CorrectArticle(string phrase);
string GetPhrase(void);
bool Continue(void);
string UpperCase(string);
string RandomItem(void);
const string PUNCTUATION = ".";
int main(){
//Variables
int turn;
bool flag;
string phrase,
article,
story, item,
storage, owner;
srand(time(NULL));
cout << "Welcome to Grandmother's Trunk 9000" << endl;
cout << "This is a memory game. Each turn a player" << endl;
cout << "Says an item to place inside a trunk. " << endl;
cout << "And the next player has to say what the " << endl;
cout << "previous player said plus his/her own item." << endl;
cout << "This will go around in revolving turns." << endl;
cout << endl << endl;
cout << "But Grandma's Trunk is a little dry..." << endl;
cout << "Let's change what the storage is and " << endl;
cout << "Who owns it." << endl << endl;
//define storage variable
cout << "What exactly is this storage?" << endl;
getline (cin, storage);
cout << "So the items are stored in " << storage << endl;
cout << endl;
//define owner
cout << "Who owns this " << storage << " ?" << endl;
getline (cin, owner);
cout << "The owner is " << owner << endl;
story = "In "+ owner + " " + storage + " you've found ";
turn = 0;
flag = Continue();
//While flag is true
while (flag) {
if (turn %2 == 0) {
item = GetPhrase();
} else {
item = RandomItem();
}
//set corrected item to article
article = CorrectArticle(item);
//advance the story every item
story = story + "\n and " + article + " " + item;
cout << story << PUNCTUATION << endl;
turn++;
flag = Continue();
}
return (0);
}
//Gives A, AN, and THE to correct words
// An if phrase starts with i,e,i,o,u or y
// A if phrase starts with other lower case letters
// The for phrases that start with an uppercase letter
string CorrectArticle(string phrase){
int i=0;
string correctedString;
string stringAn;
string stringA;
string stringThe;
stringAn= " an ";
stringA = " a ";
stringThe= "The ";
if (GetPhrase().at(i) = "a" or "e" or "i" or "u"){
correctedString = stringAn + GetPhrase();
}else if (isupper(GetPhrase().at(i))){
correctedString = stringThe + GetPhrase();
}else{
correctedString = stringA + GetPhrase();
}
return correctedString;
}
//This function takes no parameters
//and returns the user's input
string GetPhrase(void){
string itemInput;
cout << "\nWhat did you find? \n" << endl;
getline (cin, itemInput);
cout << "\nYou found " << itemInput << endl;
cin.ignore();
return itemInput;
}
//Asks user if they wish to continue
bool Continue(void){
//return false if no, true if yes
string continueString;
cout << "Would you like to continue?";
cout << " Yes or No would suffice" << endl;
getline(cin,continueString);
UpperCase(continueString);
cout << "You picked " << continueString;
if (UpperCase(continueString).find("NO") != string::npos){
return false;
} else if (UpperCase(continueString).find("YES") != string::npos){
return true;
}
}
//Changes the string to uppercase
string UpperCase(string stringUpper){
int i = 0;
while (i<stringUpper.size()){
stringUpper[i] = toupper(stringUpper[i]);
i++;
}
return stringUpper;
}
//Randomizes items found in game
string RandomItem(void){
int randomNumber;
int maxNumberOfItems = 5;
string randomizedItem;
randomNumber= rand() % maxNumberOfItems;
switch (randomNumber){
case 0:
randomizedItem = "Smaug";
break;
case 1:
randomizedItem = "Batman";
break;
case 2:
randomizedItem = "Yoda";
break;
case 3:
randomizedItem = "Paul Atreides";
break;
case 4:
randomizedItem = "Captain Kirk";
break;
default:
cout << "ERRORRRR! PANIC!" << endl;
}
return randomizedItem;
}
Remember that = is assignment, == for compare.
Also remember that you have to compare variable with value, such as:
if ((string == "a") or (string == "e") ...
If the or works for you, all the best. I've only been able to use ||. Must be compiler conformity issues.
Try this:
bool is_vowel(char letter)
{
const std::string vowels("aeiouAEIOU");
return (vowels.find_first(letter) != std::string::npos);
}
In other words, I place all the vowels in a string a search the string. If there is a match, the letter is a vowel.