Skip to main content
GameDev.net gamedev.net
🔒 Locked

Problem with an enumerator

Started by Poro Feb 17, 2008 at 1:14 PM 13 replies 2.6k views
Original Post
Poro
Poro
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;
}


ToohrVyk
ToohrVyk
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}

Crypter
Crypter
Knowing that enums are simply integers, you can also just define mychoice like this:
int mychoice = easy;
...And it should compile fine.
jonahrowley
jonahrowley
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.
ToohrVyk
ToohrVyk
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...
jonahrowley
jonahrowley
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.
jonahrowley
jonahrowley
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.
Poro
Poro
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;}
Evil Steve
Evil Steve
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.
Poro
Poro
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;}
Evil Steve
Evil Steve
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.
Poro
Poro
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.
Poro
Poro
Anyone?
kimi
kimi
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.
Poro
Poro
Got it working now. Thank you very much!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.