C++ Text based game [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am currently making a small console based text game in C++ with visual studio 2010.
I have encounted the problem of; when I get my name entered and difficulty selected I go to make the introductory text and I enter :
cout <<"Welcome "<<userName<<"... You are a lone: "<<pickRace<<" Your journey will be a "<<difficulty<<" one.";
And I want it to show up as : Welcome Blake... you are a lone Human/Orc your journey will be a easy/medium/hard one.
But I comes up as Welcome Blake... you are a lone 1/2 your jouney will be a 1/2/3 one.
this is a problem I think due to my switch's could anyone tell me how I need to rewrite them to get it appear with the name instead of numbers?
original code :
cout <<"Please pick your race: \n";
cout <<"1 - Human\n";
cout <<"2 - Orc\n";
int pickRace;
cout <<"Pick your race: ";
cin >>pickRace;
switch (pickRace)
{
case 1:
cout <<"You picked the Human race.\n";
break;
case 2:
cout <<"You Picked the Orc race\n";
break;
default:
cout <<"Error - Invalid imput; only 1 or 2 allowed.\n";
}
int difficulty;
cout <<"\nPick your level diffuculty: \n";
cout <<"1 - Easy\n";
cout <<"1 - Medium\n";
cout <<"3 - Hard\n";
cout <<"Pick your level difficulty: ";
cin >>difficulty;
switch (difficulty)
{
case 1:
cout <<"You picked Easy.\n\n";
break;
case 2:
cout <<"You picked Medium.\n\n";
break;
case 3:
cout <<"You picked Hard.\n\n";
break;
default:
cout <<"Error - Invalid imut; only 1,2 or 3 allowed.\n";
}

You are storing pickRace and difficulty as integers. Try doing something like:
int pickRace;
string raceText; //we will store the race type using this
cout <<"Pick your race: ";
cin >>pickRace;
switch (pickRace)
{
case 1:
cout <<"You picked the Human race.\n";
raceText = "Human";
break;
case 2:
cout <<"You Picked the Orc race\n";
raceText = "Orc";
break;
default:
cout <<"Error - Invalid imput; only 1 or 2 allowed.\n";
}
Note the raceText string variable.
Repeat this for difficulty.
Then use raceText and difficultyText to print your message:
out <<"Welcome "<<userName<<"... You are a lone: "<<raceText<<" Your journey will be a "<<difficultyText<<" one.";

Consider using enums and overload operator<< and operator>> for them:
#include <iostream>
#include <cassert>
enum difficulty { EASY = 1, MEDIUM = 2, HARD = 3 };
std::istream& operator>>( std::istream& is, difficulty& d )
{
int i;
is >> i;
assert( i > 0 && i < 4 ); // TODO: Use real error handling, throw an exception
d = difficulty( i );
return is;
}
std::ostream& operator<<( std::ostream& os, difficulty d )
{
switch( d ) {
case EASY: return os << "easy";
case MEDIUM: return os << "medium";
case HARD: return os << "hard";
}
return os << "unknown[" << (int)d << "]";
}
int main()
{
difficulty d;
std::cout << "Pick difficulty: 1-easy, 2-medium, 3-hard: ";
std::cin >> d;
std::cout << "You picked difficulty: " << d << std::endl;
}

Why do you expect it to print string when you are storing choices as ints...
You can use std::map
#include <map>
std::map<int, std::string> difficulty;
difficulty[1] = "easy";
difficulty[2] = "medium";
difficulty[3] = "hard";
int choice_difficulty;
std::cin>>choice_difficulty;
/*Check if user entered correct number*/
std::map<int, std::string>::iterator it = difficulty.find(choice_difficulty);
if(it == difficulty.end())
std::cout << "wrong choice";
cout <<"Welcome "<<userName<<" Your journey will be a "<<difficulty[choice_difficulty];

You may want to use lookup tables to convert between enums or numeric IDentifiers (IDs) and the text they represent.
For example:
struct Race_Text_Entry
{
const char * text;
unsigned int id;
};
static const Race_Text_Entry race_name_table[] =
{
{"Unknown", 0},
{"Human", ID_HUMAN_RACE},
{"Orc", ID_ORC_RACE},
{"Elf", ID_ELF_RACE},
};
static const unsigned int NUM_RACE_ENTRIES =
sizeof(race_name_table) / sizeof(race_name_table[0]);
std::string Race_ID_To_Text(unsigned int id)
{
unsigned int i = 0;
std::string race_name = "Race unknown";
for (i = 0; i < NUM_RACE_ENTRIES; ++i)
{
if (race_name_table[i].id == id)
{
race_name = race_name_table.text;
break;
}
}
return race_name;
}
int main(void)
{
std::cout << "My race: " << Race_ID_To_Text(ID_RACE_HUMAN) << "\n";
return 0;
}
A nice advantage to the constant lookup table as an array, is that it can be stored in the read-only data section of the program and loaded with the constant data. The initialization time is negligible compared with creating a std::map variable during initialization.

pickRace and difficulty are Integers. You're printing integers instead of the actual difficulty. You need to somehow logically represent the difficulty (and pickRace)

Related

c++: for not working as intended [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
My question is when I run the code,and call for the list,so I press 3,nothing happens and it just skips over the code in for(). Why does this occur and how can I fix it?
Simple code would be welcome.I am now to this.
The first two int before the main checks if the student is qualified for the school,or not.i tested those and they are working great.
The struct describes a student.He/She has a name(nev),marks (bacmagy,bacrom,bacmat,bacvalasz).A boolean value(langexam) is present,to represent is the student has a language exam or not.
bsiker is true,if the formula in calculateBac turns out to be true.
atmente is true,if bsiker and langexam are both true.
The listing would spit out the name,bsiker and atmente.
#include <iostream>
using namespace std;
int atmegye(bool elso, bool masodik){
if (elso && masodik)
return true;
else
return false;
}
int calculateBac(double magy, double mat, double rom, double val){
double osszeg = magy + mat + rom + val;
osszeg = osszeg / 4;
if (magy < 5 || mat < 5 || rom < 5 || val < 5 || osszeg < 6)
return false;
else
return true;
}
int main(){
struct diak{
char nev[32];
bool langexam, atmente, bsiker;
double bacmagy, bacrom, bacmat, bacvalasz, bac;
};
diak v[150];
bool cap = false;
int opcio;
int j, n = 0;
int i = 0;
do{
cout << "\n Welcome. \n 1-new studient \n 2-Change a studient's details \n 3-List \n 4-Exit \n";
cin >> opcio;
switch (opcio){
case 4:{
return 0;
}
case 1:{
cout << "Please give the name of the student: ";
cin >> v[i].nev;
cout << "Hungarian mark: ";
cin >> v[i].bacmagy;
cout << "Romanian mark: ";
cin >> v[i].bacrom;
cout << "Maths mark: ";
cin >> v[i].bacmat;
cout << "Optional mark: ";
cin >> v[i].bacvalasz;
cout << " Do you have a language exam? Please respond with 1 or 0: ";
cin >> v[i].langexam;
v[i].bsiker = calculateBac(v[i].bacmagy, v[i].bacrom, v[i].bacmat, v[i].bacvalasz);
v[i].atmente = atmegye(v[i].bsiker, v[i].langexam);
i = i + 1;
i = n;
cout << n;
break;
}
case 3: {
for(i = 0; i < n; i++)
cout << v[i].nev << " " << v[i].bsiker << " " << endl;
break;
}
}
}while (opcio != 5);
}
This line is wrong:
i = n;
it should be:
n = i;
Your code is just undoing the i = i + 1; line that precedes it.
n is initialized as 0 and never set to any other value. Therefore your for loop is not supposed to run any iteration
The problem is in the for loop's conditional. You initialized the value of n to 0, and that value never seems to change. The variable i is also initialized to 0 inside the for loop. When the user chooses option 3, the for loop conditional ( 0 < 0) is evaluated which is false, so the for loop is skipped every time. So, to fix this problem, you need to update the value of n somewhere in your code, or you need to change your conditional statement. Hope this helps!
I know this probably won't help for your assignment, but here's a (one of many) way to handle this is a more c++-like manner, and without using OOP.
The standard library and the c++ type system give us plenty of useful tools to avoid writing bugs in the first place (that's really nice!), and find the one that are left at compile-time (saves a ton of time!). That's what the biggest difference between c and c++ is, and it is a very important one.
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
// fixed-size record to save in data file, for example.
struct diak{
char nev[32];
bool langexam, atmente, bsiker;
double bacmagy, bacrom, bacmat, bacvalasz, bac;
};
void atmegye(diak& student)
{
student.atmente = student.bsiker && student.langexam;
}
void calculateBac(diak& student) // computes grades average, checks if passed.
{
double osszeg = student.bacmagy + student.bacmat + student.bacrom + student.bacvalasz;
student.bac = osszeg / 4.0;
student.bsiker = student.bacmagy >= 5
&& student.bacrom >= 5
&& student.bacmat >= 5
&& student.bacvalasz >= 5
&& student.bac >= 5; // this last test unnecessary, but rules are rules.
}
void AddNewStudent(std::ostream& os, std::istream& is, std::vector<diak>& students)
{
diak new_student;
std::string temp;
while(temp.empty())
{
os << "Student name: ";
is >> temp; // using a temp buffer avoids out of bounds errors
}
if (temp.length() >= sizeof(new_student.nev))
temp.resize(sizeof(new_student.nev) - 1);
strcpy(new_student.nev, temp.c_str());
// input values below SHOULD be validated for range (0-100)
// or whatever makes sense for your school.
os << "Hungarian mark: "; is >> new_student.bacmagy;
os << "Romanian mark: "; is >> new_student.bacrom;
os << "Maths mark: "; is >> new_student.bacmat;
os << "Optional mark: "; is >> new_student.bacvalasz;
// example validation. Validating user input is the worst!
// above ^^^ grades ^^^ can use a common function for validation.
for(;;)
{
os << " Do you have a language exam? Please respond with 1 or 0:";
is >> temp;
if (temp == "0")
{
new_student.langexam = false;
break;
}
if (temp == "1")
{
new_student.langexam = true;
break;
}
// not a valid entry, try again!
}
calculateBac(new_student);
atmegye(new_student);
students.push_back(new_student);
}
void EditSudent(std::ostream& os, std::istream& is, std::vector<diak>& students)
{
// query which student then edit using streams 'os' and 'is' for i/o.
}
// could also be used to write to file...
void PrintStudents(std::ostream& os, const std::vector<diak>& students)
{
// maybe by printing a student number you could reuse this
// function from EditStudent()...
//
// At the same time, it is only 2 lines of code. You decide.
for(size_t i = 0; i < students.size(); i++)
os << students[i].nev << " " << students[i].bsiker << "\n";
os.flush();
}
int main()
{
std::vector<diak> students; // could also be an std::list<>
while(true) // 1 less line of code than do {...} while, and easier to read.
{
int opcio = 0;
std::cout << "\n Welcome."
"\n 1-new studient"
"\n 2-Change a studient's details"
"\n 3-List "
"\n 4-Exit \n";
std::cin >> opcio;
switch (opcio)
{
case '1':
AddNewStudent(std::cout, std::cin, students);
break;
case 2:
EditSudent(std::cout, std::cin, students); // << queries student and edit that
break;
case 3:
PrintStudents(std::cout, students);
break;
case 4:
return 0;
}
}
}
Note how the tasks are very well delimited into their own function, this also helps finding bugs faster, as it makes the code easier to read and reason about (the famous divide and conquer strategy).
Having the students array (or list) as a single entity simplifies its management, no extra variable to keep up to date, etc...
In a more serious application, the input validation would be best done using a template, and would give the user an escape character so he could cancel adding the new student at any time.

classes and creating multiple objects in C++

I've written a program for my C++ class and I ran into a little problem which I'm not quite sure how to solve. Some of you may be familiar with this textbook exercise as I've seen questions asked about it on the site before, but I was unable to find any simple fix.
I have to create a class which is used to store information about a pizza. I've got the program written and functional, but I need the class call to loop through a series of iterations based on the user's input. I know that this can be achieved using vectors, something we haven't hit yet in the semester, but will get to soon enough I'm sure. Is there a way to do this without vectors?
Here's the class.
class Pizza
{
private:
int type;
int size;
int numCheeseTopping;
int numPepperoniTopping;
bool cheeseTopping;
bool pepperoniTopping;
public:
Pizza();
int getType();
int getSize();
bool getCheese();
bool getPepperoni();
void setType(int t);
void setSize(int s);
void setCheese(bool choice, int temp);
void setPepperoni(bool choice, int temp);
void outputDescription();
double computePrice();
void outputPrice();
};
And the constructor.
Pizza::Pizza()
{
// Set initial class values
type = DEEPDISH;
size = SMALL;
cheeseTopping = false;
numCheeseTopping = 0;
pepperoniTopping = false;
numPepperoniTopping = 0;
}
Main is only two functions.
// Main function
int main()
{
// Call global functions
welcomeMsg();
buildPizza();
return 0;
}
I have a feeling that my problem lies in the buildPizza function, as it calls other functions as well as creating the objects. Here it is...
void buildPizza()
{
char pType, pSize, tempCheese, tempPepperoni;
int type = 0, size = 0, numCheeseTopping = 0, numPepperoniTopping = 0;
// Ask user what size pizza they would like.
cout << "What size pizza would you like?" << endl;
cout << "\tS: Small" << endl;
cout << "\tM: Medium" << endl;
cout << "\tL: Large" << endl;
cout << "Size: ";
cin >> pSize;
// Determine which size the user input and convert the
// result.
switch (pSize)
{
case 'S':
case 's':
size = SMALL;
break;
case 'M':
case 'm':
size = MEDIUM;
break;
case 'L':
case 'l':
size = LARGE;
break;
}
// Ask the user which type of pizza they would like.
cout << endl << "What type pizza would you like?" << endl;
cout << "\tD: Deepdish" << endl;
cout << "\tH: Hand-Tossed" << endl;
cout << "\tP: Pan" << endl;
cout << "Type: ";
cin >> pType;
// Determine which type the user input and convert the
// result.
switch (pType)
{
case 'D':
case 'd':
type = DEEPDISH;
break;
case 'H':
case 'h':
type = HANDTOSSED;
break;
case 'P':
case 'p':
type = PAN;
break;
}
// Call Pizza Class.
Pizza myPizza;
// Call Pizza Class functions.
myPizza.setSize(size);
myPizza.setType(type);
// Ask user whether they want cheese or not.
cout << endl << "Would you like cheese (y/n)? ";
cin >> tempCheese;
// If so call setCheese.
if (tempCheese == 'Y' || tempCheese == 'y')
{
cout << "How many cheese toppings would you like? ";
cin >> numCheeseTopping;
myPizza.setCheese(true, numCheeseTopping);
}
// Ask user whether they want pepperoni or not.
cout << endl << "Would you like pepperoni (y/n)? ";
cin >> tempPepperoni;
// If so call setPepperoni.
if (tempPepperoni == 'Y' || tempPepperoni == 'y')
{
cout << "How many pepperoni toppings would you like? ";
cin >> numPepperoniTopping;
myPizza.setPepperoni(true, numPepperoniTopping);
}
// Call outputDescription to give user an overview
// of their order.
cout << endl << endl;
myPizza.outputDescription();
cout << endl;
// Compute the cost of the pizza and display it.
myPizza.outputPrice();
}
Basically, I'd like the program to ask the user how many pizzas they would like to evaluate, create that many class iterations, then cycle through 'building' or 'ordering' each pizza, then display a total and return 0.
As I look at the code now I can take the last two function calls out of buildPizza and move the calls into main, but this will not solve my problem. Only an oversight I literally just noticed within the program.
Is there an easy way to create, say, 200 new objects all at once at runtime. Each one with a different name? Should I just pick a number to evaluate and force the user to enter information for that many objects? Right now, the program evaluates one pizza and quits.
I'd like something like this to happen:
User asks program to create a 5 pizza order.
Program creates 5 pizza objects.
Program iterates through each object getting and setting information for each one.
Program displays some stuff and returns 0.
Is this possible with my code, or do I need to consider a rewrite? Any guidance the community can give me will be immensely helpful.
Thanks.
Kyle
Since you cnanot use arrays or vectors, a simple for would suffice.
auto nrPizzas = getNumberOfPizzasFromUserInput();
for(int i = 0; i < nrPizzas; i++) {
auto pizza = Pizza{};
// do your stuff here.
output to the screen here();
}
You can prompt for the number of pizzas user want and then create a dynamic array of that much pizzas and then iterate through their build function or else you can make a linked-list with struct type of pizza and then rewrite the main logic. Second approach is advised if you do not want to prompt that how many pizza's the user wants to order.

I need to user an enumerations to represent difficulties levels. I keep getting an error about using cin>>

I have to use a enumerations to represent the difficulty levels. Here is the code.
// Menu Chooser
// Demonstrates the switch statement
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Difficulty Levels\n\n";
cout << "1 - Easy\n";
cout << "2 - Normal\n";
cout << "3 - Hard\n\n";
enum userChoice {Easy, Normal, Hard};
userChoice choice;
cout << "Choice: ";
cin >> choice;
switch (choice)
{
case 1:
cout << "You picked Easy.\n";
break;
case 2:
cout << "You picked Normal.\n";
break;
case 3:
cout << "You picked Hard.\n";
break;
default:
cout << "You made an illegal choice.\n";
}
return 0;
}
and the error message:
error C2678: binary '>>' : no operator found which takes a left-hand
operand of type 'std::istream' (or there is no acceptable conversion)
There is no default implementation of the >> operator for taking an input and mapping it to an enum. You will need to take in an int as an input and then map it to the enum. Alternatively, you could write an overload for the >> operator that maps the input to your enum.
Of course, looking at your code, you don't seem to be using the defined enum for anything. Perhaps you could remove it and use an int instead?
You need to place your enum values into your cases:
switch (choice)
{
case Easy:
cout << "You picked Easy.\n";
break;
case Normal:
cout << "You picked Normal.\n";
break;
case Hard:
cout << "You picked Hard.\n";
break;
default:
cout << "You made an illegal choice.\n";
}
To convert from text to enum type, I suggest you use a table (your instructor probably hasn't covered the topic of std::map which would be the preferred method).
struct Enum_Entry
{
UserChoice value;
const char * text;
};
static const Enum_Entry lookup_table[] =
{
{Easy, "easy"},
{Normal, "normal"},
{Hard, "hard"},
};
static const unsigned int items_in_table =
sizeof(lookup_table) / sizeof(lookup_table[0]);
std::string selection_text;
// Input enum as text
std::cin >> selection_text;
// Convert to lower case to make comparison easier
std::transform(selection_text.begin(), // Start of range
selection_text.end(), // End of range
selection.begin(), // Destination for transformation.
std::tolower); // Transformation function.
// Lookup the text into the table and retrieve the enum value.
UserChoice choice = Easy;
for (unsigned int i = 0; i < items_in_table; ++i)
{
if (selection_text == lookup_table[i].text)
{
choice = lookup_table[i].value;
break;
}
}
Another method is to use an if-else-if ladder:
choice = easy;
if (selection_text == "easy")
{
choice = Easy;
}
else if (selection_text == "hard")
{
choice = Hard;
}
else if (selection_text == "normal")
{
choice = Normal;
}
else
{
choice = Easy;
}
When reading user input, it is not safe to expect they will enter a correct value. However, this seems extreme for your assignment.
My first thought is to just read in an int, then cast it to the enum.
int input;
cin >> input;
userChoice choice = (userChoice)input;
This should work, however I haven't tested it.

Switch-statement inside a while-loop which loop infinitely

Here is my code:
int main()
{
int nothing;
string name;
int classnum;
bool classchosen;
string classname;
cout << "Welcome adventurer, your journey is about to begin.\n\n";
cout << "Firstly, what's your name? ";
cin >> name;
classchosen = false;
while (classchosen == false)
{
cout << "\n\nNow, " << name << ", choose your class entering its number.\n\n";
cout << "1- Warrior\n" << "2- Mage\n" << "3- Paladin\n" << "4- Monk\n\n";
cout << "Class number: ";
cin >> classnum;
switch(classnum){
case 1:
classname = "Warrior";
classchosen = true;
break;
case 2:
classname = "Mage";
classchosen = true;
break;
case 3:
classname = "Paladin";
classchosen = true;
break;
case 4:
classname = "Monk";
classchosen = true;
break;
default:
cout << "\nWrong choice, you have to enter a number between 1 and 4.\n" << endl;
break;
}
}
cout << "\nSo you are a " << classname << " ? Well, tell me something more about you...\n";
cin >> nothing;
return 0;
}
Now, when I run it and input a string (for example "fjdfhdk") when it asks about the class number, the program loops infinitely instead of going in the default statement, writing again the question and letting me choose another class. Why?
Try something like this:
#include <sstream>
#include <string>
using namespace std;
int getInt(const int defaultValue = -1){
std::string input;
cin >> input;
stringstream stream(input);
int result = defaultValue;
if(stream >> result) return result;
else return defaultValue;
}
//..in main
cout << "Class number: ";
int classNum = getInt();
switch(classNum){ .... }
The reason why it fails in your case is because cin is trying to read a bunch of chars into a int variable. You can either read it as a string and convert as necessary, or you can check the cin state explicitly when reading into a int variable by checking if any of the fail bits are set. The fail bits would be set if for example you try to read bunch of chars into an int.
Because you're reading into an int, and the read fails. This
has two effects:
your use of classnum afterwards is undefined behavior, and
the stream has memorized the error condition, so you can
check it later.
As long as the error condition is not cleared, all further
operations on the stream are no-ops. The simplest changes in
your program to make this work would be:
std::cin >> classnum;
if ( !std::cin ) {
classnum = 0;
std::cin.clear();
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}
switch ( classnum ) // ...
In case of an error, this sets classnum to a known value,
clears the error state, and skips all input up to the next
newline. (Otherwise, you'll just fail again, because the
characters which triggered the error are still there.)
Consider, however, using a separate function to extract the int,
and using getline, as per user814628's suggestion. The above
is more to explain to you what is happening, and why your see
the symptoms you see. user814628's suggestion is far better
software engineering.

How do I use an enum value in a switch statement in C++?

I would like to use an enum value for a switch statement. Is it possible to use the enum values enclosed in "{}" as choices for the switch()"?
I know that switch() needs an integer value in order to direct the flow of programming to the appropriate case number. If this is the case, do I just make a variable for each constant in the enum statement?
I also want the user to be able to pick the choice and pass that choice to the switch() statement.
For example:
cout << "1 - Easy, ";
cout << "2 - Medium, ";
cout << "3 - Hard: ";
enum myChoice { EASY = 1, MEDIUM = 2, HARD = 3 };
cin >> ????
switch(????)
{
case 1/EASY: // (can I just type case EASY?)
cout << "You picked easy!";
break;
case 2/MEDIUM:
cout << "You picked medium!";
break;
case 3/HARD: // ..... (the same thing as case 2 except on hard.)
default:
return 0;
}
You can use an enumerated value just like an integer:
myChoice c;
...
switch( c ) {
case EASY:
DoStuff();
break;
case MEDIUM:
...
}
You're on the right track. You may read the user input into an integer and switch on that:
enum Choice
{
EASY = 1,
MEDIUM = 2,
HARD = 3
};
int i = -1;
// ...<present the user with a menu>...
cin >> i;
switch(i)
{
case EASY:
cout << "Easy\n";
break;
case MEDIUM:
cout << "Medium\n";
break;
case HARD:
cout << "Hard\n";
break;
default:
cout << "Invalid Selection\n";
break;
}
Some things to note:
You should always declare your enum inside a namespace as enums are not proper namespaces and you will be tempted to use them like one.
Always have a break at the end of each switch clause execution will continue downwards to the end otherwise.
Always include the default: case in your switch.
Use variables of enum type to hold enum values for clarity.
see here for a discussion of the correct use of enums in C++.
This is what you want to do.
namespace choices
{
enum myChoice
{
EASY = 1 ,
MEDIUM = 2,
HARD = 3
};
}
int main(int c, char** argv)
{
choices::myChoice enumVar;
cin >> enumVar;
switch (enumVar)
{
case choices::EASY:
{
// do stuff
break;
}
case choices::MEDIUM:
{
// do stuff
break;
}
default:
{
// is likely to be an error
}
};
}
You can use a std::map to map the input to your enum:
#include <iostream>
#include <string>
#include <map>
using namespace std;
enum level {easy, medium, hard};
map<string, level> levels;
void register_levels()
{
levels["easy"] = easy;
levels["medium"] = medium;
levels["hard"] = hard;
}
int main()
{
register_levels();
string input;
cin >> input;
switch( levels[input] )
{
case easy:
cout << "easy!"; break;
case medium:
cout << "medium!"; break;
case hard:
cout << "hard!"; break;
}
}
I had a similar issue using enum with switch cases.
Later, I resolved it on my own....below is the corrected code, and perhaps this might help.
//Menu Chooser Programme using enum
#include <iostream>
using namespace std;
int main()
{
enum level{Novice=1, Easy, Medium, Hard};
level diffLevel = Novice;
int i;
cout << "\nEnter a level: ";
cin >> i;
switch(i)
{
case Novice:
cout << "\nyou picked Novice\n"; break;
case Easy:
cout << "\nyou picked Easy\n"; break;
case Medium:
cout << "\nyou picked Medium\n"; break;
case Hard:
cout << "\nyou picked Hard\n"; break;
default:
cout << "\nwrong input!!!\n"; break;
}
return 0;
}
You should keep in mind that if you are accessing a class-wide enum from another function, even if it is a friend, you need to provide values with a class name:
class PlayingCard
{
private:
enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES };
int rank;
Suit suit;
friend std::ostream& operator<< (std::ostream& os, const PlayingCard &pc);
};
std::ostream& operator<< (std::ostream& os, const PlayingCard &pc)
{
// Output the rank ...
switch(pc.suit)
{
case PlayingCard::HEARTS:
os << 'h';
break;
case PlayingCard::DIAMONDS:
os << 'd';
break;
case PlayingCard::CLUBS:
os << 'c';
break;
case PlayingCard::SPADES:
os << 's';
break;
}
return os;
}
Note how it is PlayingCard::HEARTS and not just HEARTS.
The user's input will always be given to you in the form of a string of characters... if you want to convert the user's input from a string to an integer, you'll need to supply the code to do that. If the user types in a number (e.g. "1"), you can pass the string to atoi() to get the integer corresponding to the string. If the user types in an english string (e.g. "EASY") then you'll need to check for that string (e.g. with strcmp()) and assign the appropriate integer value to your variable based on which check matches. Once you have an integer value that was derived from the user's input string, you can pass it into the switch() statement as usual.
#include <iostream>
using namespace std;
int main() {
enum level {EASY = 1, NORMAL, HARD};
// Present menu
int choice;
cout << "Choose your level:\n\n";
cout << "1 - Easy.\n";
cout << "2 - Normal.\n";
cout << "3 - Hard.\n\n";
cout << "Choice --> ";
cin >> choice;
cout << endl;
switch (choice) {
case EASY:
cout << "You chose Easy.\n";
break;
case NORMAL:
cout << "You chose Normal.\n";
break;
case HARD:
cout << "You chose Hard.\n";
break;
default:
cout << "Invalid choice.\n";
}
return 0;
}
You can cast enum with int.
enum TYPE { one, two, tree };
TYPE u;
u = two;
switch( int( u ) ){
case one :
action = do_something ;
break;
case two:
action = do_something_else;
break;
}