Sign in to follow this  

Problem with an enumerator

This topic is 3571 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello! So I am reading this book called Beginning C++ Game Programming by Michael Dawson. I just finished reading Chapter 2 about loops and I got stuck in one of the exercises. I am asked to change the original code to use enumerator, but I can't get it to work. I get error message on compiling saying "Line 17 - no match for 'operator>>' in 'std::cin >> mychoice' ". As far as I can tell, my cin command is somehow bugged. The code works fine without it. I use Dev-C++ to compile my code, as the book recommends it. So what is the problem? Here is the original code:
// Menu Chooser
// Demonstrates the switch statement

#include <iostream>
using namespace std;

int main() 
{
	cout << "Difficulty Levels\n\n";
	cout << "1 - Easy\n";
	cout << "2 - Normal\n";
	cout << "3 - Hard\n\n";

	int 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;
}

My code:
// Menu Chooser
// Demonstrates the switch statement

#include <iostream>
using namespace std;

int main() 
{
	cout << "Difficulty Levels\n\n";
	cout << "1 - Easy\n";
	cout << "2 - Normal\n";
	cout << "3 - Hard\n\n";

	enum choice {easy = 1, normal, hard};
	choice mychoice = easy;
	cout << "Choice: ";
	cin >> mychoice;

	switch (mychoice)
	{
	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";
	}

    system("pause");
    return 0;
}


Share this post


Link to post
Share on other sites
std::cin >> x is only implemented for existing types. If you create a new type, such as an enumeration, then you will have to implement it yourself if you want to use it.

In this particular situation, however, there is a simpler solution: read the answer into an integer, and then convert that integer to an enumeration value.

choice mychoice = easy;
cout << "Choice: ";
{
int temp;
if (cin >> temp)
switch (temp)
{
case 1: mychoice = easy; break;
case 2: mychoice = medium; break;
case 3: mychoice = hard; break;
default: ;// error
}
else
; // error
}

Share this post


Link to post
Share on other sites
That's because there is no operator>> defined for your enum type. In order to input your enum type directly from an istream, you have to create an operator for it something like this:


istream& operator>>( istream& i, choice& c ) {
int choice;
i >> choice;

switch(choice) {
case easy:
case normal:
case hard:
c = choice;
return i;
default:
// Out of range, you should throw an exception here
throw some_exception();
}

// This might be needed to silence a warning, even
// though this code can never be reached.
return i;
}



You'll also have a to define your enum type at a wider scope so both this overloaded operator and the code that uses it can see it.

Share this post


Link to post
Share on other sites
Quote:
Original post by jonahrowleyswitch(choice) {
case easy:
case normal:
case hard:
c = choice;


Ooo, nice! It's short and non-brittle [smile] though it does break when the enumeration values change with respect to what is displayed on the menu screen...

Share this post


Link to post
Share on other sites
Quote:
Original post by Crypter
Knowing that enums are simply integers, you can also just define mychoice like this:
int mychoice = easy;
...And it should compile fine.


That can result in undefined behavior. If the integer value you assign is not represented in an enum, code expecting the enum to be sane will fail.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Ooo, nice! It's short and non-brittle [smile] though it does break when the enumeration values change with respect to what is displayed on the menu screen...


That just means it needs further abstraction to be a functional and flexible menu class. This is just an example from a book he's exploring though.

Share this post


Link to post
Share on other sites
Sorry for the late answer, but thanks for the replies! I tried what ToohrVyk suggested, but I still have one problem. When I put in an illegal number like five, it does not print correct answer.
Picture about the problem:
http://img504.imageshack.us/img504/7532/gamedevprobdr8.jpg

Here is my code:

#include <iostream>
using namespace std;

int main()
{
cout << "Welcome to menu chooser program!\n";
cout << "Choose a difficulty:\n";
cout << "1. Easy\n";
cout << "2. Normal\n";
cout << "3. Hard \n";

enum choice{EASY = 1,NORMAL,HARD};
choice myChoice = NORMAL;

cout << "Choice: ";
int temp;
if (cin >> temp)
switch (temp)
{
case 1: myChoice = EASY;
break;
case 2: myChoice = NORMAL;
break;
case 3: myChoice = HARD;
break;
default: ;
}
switch (myChoice)
{
case 1:
cout << "\nYou chose: Easy " << endl;
break;
case 2:
cout << "You chose: Normal" << endl;
break;
case 3:
cout << "You chose: Hard" << endl;
break;
default:
cout << "Illegal choice" << endl;
break;
}

system("pause");
return 0;
}



Share this post


Link to post
Share on other sites
temp isn't getting intialised, so it has a random value - Which just happens to be 2 in this case. Either set it to some value initially (Like -1, which isn't going to be a valid enum value), or do so in the default case.

Share this post


Link to post
Share on other sites
Did I do something wrong, as it still does not work. Still the same error.

My edited code:

#include <iostream>
using namespace std;

int main()
{
cout << "Welcome to menu chooser program!\n";
cout << "Choose a difficulty:\n";
cout << "1. Easy\n";
cout << "2. Normal\n";
cout << "3. Hard \n";

enum choice{EASY = 1,NORMAL,HARD};
choice myChoice = NORMAL;

cout << "Choice: ";
int temp = -1;
if (cin >> temp)
switch (temp)
{
case 1: myChoice = EASY;
break;
case 2: myChoice = NORMAL;
break;
case 3: myChoice = HARD;
break;
default: ;
}
switch (myChoice)
{
case 1:
cout << "\nYou chose: Easy " << endl;
break;
case 2:
cout << "You chose: Normal" << endl;
break;
case 3:
cout << "You chose: Hard" << endl;
break;
default:
cout << "Illegal choice" << endl;
break;
}

system("pause");
return 0;
}

Share this post


Link to post
Share on other sites
Oh, sorry - I was wrong (But it's good practice to initialise all your variables anyway). The problem is that you initialise choice to NORMAL as a default, but never change it. I'd do this:
enum choice{EASY = 1,NORMAL,HARD,INVALID};
choice myChoice = INVALID;

Then just check for INVALID in your switch statement. Alternatively, change the code so it keeps looping until the user enters a valid choice, and then display the selection.

EDIT: Nitpick: When you print out the "You chose blah" text, it's nicer to use E.g. case EASY: instead of case 1:. That's the whole point in enumerations, so you can replace an integer value with a symbol name.

Share this post


Link to post
Share on other sites
I am sorry, but I still don't get it. Shouldn't this part set new value to myChoice? I understood it goes like this: I enter number two, and the program takes it to int temp. Then the switch compares the number two and founds out that it matches case NORMAL. Then it will insert NORMAL to myChoice? So why does it not change the number in myChoice?
int temp = INVALID;
if (cin >> temp)
switch (temp)
{
case EASY: myChoice = EASY;
break;
case NORMAL: myChoice = NORMAL;
break;
case HARD: myChoice = HARD;
break;
default: ;
}


I just modified the code to use enumerators instead of values, as you suggested. Here it is:

#include <iostream>
using namespace std;

int main()
{
cout << "Welcome to menu chooser program!\n";
cout << "Choose a difficulty:\n";
cout << "1. Easy\n";
cout << "2. Normal\n";
cout << "3. Hard \n";

enum choice{EASY = 1,NORMAL,HARD,INVALID};
choice myChoice = INVALID;

cout << "Choice: ";
int temp = INVALID;
if (cin >> temp)
switch (temp)
{
case EASY: myChoice = EASY;
break;
case NORMAL: myChoice = NORMAL;
break;
case HARD: myChoice = HARD;
break;
default: ;
}
switch (myChoice)
{
case EASY:
cout << "\nYou chose: Easy " << endl;
break;
case NORMAL:
cout << "You chose: Normal" << endl;
break;
case HARD:
cout << "You chose: Hard" << endl;
break;
default :
cout << "Illegal choice!" << endl;
break;
}

system("pause");
return 0;
}



Sorry for the delay in my answer.

Share this post


Link to post
Share on other sites
OK I tried your program. It works for me. Haha I have a nice book [grin]



#include<iostream>

using namespace std;

int main()
{
cout<< "Difficulty Levels\n\n";
cout<< "1 - Easy\n";
cout<< "2 - Normal\n";
cout<< "3 - Hard\n\n";

enum choice {easy=1,normal,hard};
int x;
choice mychoice;

cout<<"\n Enter your choice:";
cin>>x;

mychoice=choice(x);

switch(mychoice)
{
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";
}

system("pause");
return 0;
}







You made mistake is here:

enum choice {easy = 1, normal, hard};
choice mychoice = easy;
cout << "Choice: ";
cin >> mychoice;
switch (mychoice)







choice mychoice = easy is wrong I think.

You should assign it to some variable like x and read the value of x.

example:
enum choice {easy=1,normal,hard};
int x;
choice mychoice;

X is some int value which you will read:

cout<<"\n Enter your choice:";
cin>>x;

mychoice=choice(x);

Then depending on the value of x. If 1 then it will go to switch case 1 and 3 then case 3.

Share this post


Link to post
Share on other sites

This topic is 3571 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this