如何在C++中使用枚举值进行switch语句?

56

我想在switch语句中使用一个enum值。是否可以将"{}"括起来的enum值作为switch()的选项呢?

我知道switch()需要一个整数值,以便将程序流程指向适当的case编号。如果是这样,我是否只需为enum语句中的每个常量创建一个变量?

我还希望用户能够选择选项并将该选项传递给switch()语句。

例如:

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

4
所有这些案例都等同于1。 - Edward Strange
12
@Noah:我相信他使用斜杠来表示“二选一”,而不是除法。虽然在数学上你是正确的,但我认为这不是他打算使用的实际代码。 - KevenK
9个回答

49

你可以像使用整数一样使用枚举值:

myChoice c;

...

switch( c ) {
case EASY:
    DoStuff();
    break;
case MEDIUM:
    ...
}

23

你已经走在了正确的轨道上。你可以将用户输入读入一个整数,然后使用switch语句:

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

最好将i初始化为一个会触发“default”情况的值,或者是被解释为I/O错误的值。 - Steve Jessop
typedef enum e { ... }; ?? 在C++中typedef是可选的,但如果存在,则应在闭括号后使用typedef名称。此外,在C++中(与C相比),您应该为变量使用枚举类型,而不是int类型(即使编译器会很乐意接受int类型)。 - David Rodríguez - dribeas
@David:typedef错误绝对不是标准形式。已修复。 我选择不将输入声明为“Choice”,因为这会使输入流操作符'>>'不明确。 - Adam Holmberg
1
变量类型没问题,但更像C++的做法是使用enum Choice { EASY = 1, MEDIUM = 2, HARD = 3 };而不是使用未命名枚举的typedef。 - David Rodríguez - dribeas
我想这是我从一位老导师那里学到的东西,从未有过改变的理由。在答案中进行了更新。 - Adam Holmberg

17

需要注意以下几点:

应该始终在命名空间内声明枚举,因为枚举不是真正的命名空间,并且你会被诱惑像使用命名空间一样使用它们。

在每个switch语句执行的结尾总是要有一个break,否则执行会一直往下进行到结尾。

在switch中总是包含default:case。

为了明确起见,请使用枚举类型的变量来保存枚举值。

这里可以找到关于在C ++中正确使用枚举的讨论。

这就是你想要做的事情。

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

}

1
为了让这个工作起来,你需要重载该枚举类型的输入流运算符“operator>>”。 - James McNellis
4
总体上来说,我同意这种方法,但是在“总是提供默认值”的情况下,我持不同意见。我理解这样做的目的是为了触发已知错误,以便如果稍后添加到枚举中,则可以轻松更正。我更喜欢实际处理输入以保证用户数据的正确性,而不是提供“默认”标记,而是让编译器警告switch语句是否存在任何超出所有测试案例的值。这样你就能得到更快的错误报告:如果将一个值添加到枚举中,编译器会进行投诉。 - David Rodríguez - dribeas
另外,您可能需要初始化 enumVar。如果 cin >> enumVar 没有写入值,则此代码会产生未定义的行为,这通常是当 operator>> 遇到错误时的情况。正如詹姆斯所说,您将为枚举重载运算符,因此即使在出现错误时也可以编写它以始终分配某些内容。 - Steve Jessop
好的评论和建议,这会让我学习在发布代码解决方案之前先进行编译:P - radman
对于“总是要有一个break...”的观点,我持不同意见。有时候你想要使用“穿透”的技巧。而且我也不同意“总是要包含default...”。你可以在switch语句之前验证你的输入。 - Xam
枚举类是否比命名空间更好的选择? - Alex

8
您可以使用 std::map 将输入映射到您的 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;
    }
}

如果字符串不匹配任何有效选项,则此函数将返回“easy”。 - dreamlax
1
我喜欢这种方法,因为它允许用户输入描述性字符串,而不是整数。虽然是小事,但对于只有很少可能值的东西,我会使用无序映射。映射(二叉树)很有趣,因为如果有数百或数千个值,映射比switch:case更有效率,只需要进行O(log N)次比较,而不是N/2次。 - user1899861
这个已经过期了,但是在你的枚举集中,将值设置为从1开始的整数。0表示默认情况。因此,枚举levels = {EASY=1,MEDIUM=2,HARD=3}; - Ahmad Bedirxan

3

我遇到了类似的问题,使用枚举和switch case结合的时候。

后来,我自己解决了这个问题……下面是修改后的代码,也许对你有帮助。

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

3

请注意,如果您从另一个函数访问类范围的枚举(即使它是友元),也需要使用类名提供值:

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

请注意,它是PlayingCard :: HEARTS,而不仅仅是HEARTS

0
#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;
}

0

你可以使用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;
}

0
用户的输入将始终以字符形式提供给您...如果您想将用户的输入从字符串转换为整数,您需要提供相应的代码。如果用户输入数字(例如“1”),则可以将字符串传递给atoi()以获取与字符串对应的整数。如果用户输入英文字符串(例如“EASY”),则需要检查该字符串(例如使用strcmp())并根据匹配情况为变量分配适当的整数值。一旦您获得了从用户输入字符串派生的整数值,就可以像往常一样将其传递到switch()语句中。

2
将输入从字符串转换为整数的代码是 int i; cin >> i;。这不是 C,所以没有必要搞乱 C 库。 - Mike Seymour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接