在 C++ 中使用枚举类型作为数组索引

3
#include <stdlib.h>
#include <stdio.h>
using namespace std;



void main(){
    char *resolutions[] = { "720x480", "1024x600", "1280x720", "1920x1080" };

    int x = 0;

    enum ResMode
    {
        p480,
        p600,
        p720,
        p1080
    }; 
    ResMode res = p480;

    printf("\nPlease enter the resolution you wish to use now by entering a number");
    printf("\n480p[0], 600p[1], 720p[2], 1080p[3]");
    gets(res);

    printf("\nThe resolution you have selected is %s", resolutions[res]);

}

基本上我想要做的是按下数字键1,然后从枚举中选择p600,并在下一行输出它作为1024x600。但是我遇到了类型转换错误。如何解决?

1
不要使用 gets。它在最新的 C++ 标准中已经不存在了。 - Brian Bi
@Brian:更好的做法是:不要承认曾经有过 gets。它因为明显的漏洞已经被最新的 C 和 C++ 标准所淘汰。 - Deduplicator
4个回答

7

看起来你想将一些项目与其他项目进行关联。通常,关联是通过查找表或映射来描述的。

std::map<ResMode, std::string> map_table =
{
  {p480,     string("720x480")},
  {p600,     string("1024x600")},
  {p720,     string("1280x720")},
  {p1080,    string("1920x1080")},
};

int main(void)
{
  cout << map_table[p480] << "\n";
  return EXIT_SUCCESS;
}

同样地,您可以将菜单选择映射到枚举。
std::map<unsigned int, ResMode> selection_map =
{
  {0, p480}, {1, p600}, {2, p720}, {3, p1080},
};

int main(void)
{
  cout << "\n"
       << "Please enter the resolution you wish to use now by entering a number\n"
       <<"480p[0], 600p[1], 720p[2], 1080p[3]";
  unsigned int selection = 0;
  cin >> selection;
  if (selection < 4)
  {
    Resmode resolution_index = selection_map[selection];
    cout << "You chose: "
         << map_table[resolution_index]
         << "\n";
  }
  return EXIT_SUCCESS;
}

3
为什么会被踩?如果这些踩的人能留下评论就好了,让人感到困惑。 - Thomas Matthews
1
这个问题被标记为C ++,因此我正在使用C ++功能。 - Thomas Matthews
1
对于使用using namespace std;gets()的OP来说,你的方法可能会让他们感到文化冲击。(我不是投票者) - myaut

2

int不能隐式转换为enum。您需要读取一个int,然后自己进行类型转换。例如:

int resInt;
scanf("%d", &resInt);
res = static_cast<ResMode>(resInt);//Note that this does not do bound checking.

我非常不喜欢这种做法,因为在转换之前应该先检查边界。如果没有这样做,你最终会得到一个奇怪的函数,它以ResMode作为参数并检查它是否真的是一个ResMode... 事实上,你有一个ResMode应该保证它是有效的。你可能需要一个函数来执行带有边界检查的转换(也许这就是你在这里想表达的,但不是很清楚)。 - OznOg

2
您可以使用“scanf”代替“gets”,例如:
scanf("%d",&res); // I recommend use scanf_s

或者使用带有std::cin的iostream库。但是在获取输入后,一定要始终检查输入是否正确。


那是一个不好的想法。标准不保证res将是“int”,而且scanf不是类型安全的。@Pradhan提供了一个更清晰的答案。 - myaut
没错,拥有一个整数并进行强制转换应该就可以完成答案了。顺便说一下,C++编译器提供了从枚举到整数的自动转换(不是反过来)。 - Drewen

0

正如其他人指出的那样,没有直接的方法可以做到这一点。但是,有一些技巧和诀窍可以使用。我将您的代码修改如下:

#include <stdlib.h>
#include <stdio.h>


#define SOME_ENUM(DO) \
    DO(_720x480)  \
    DO(_1024x600) \
    DO(_1280x720) \
    DO(_1920x1080)

#define MAKE_ENUM(VAR) VAR,
enum class RESOLUTIONS
{
    SOME_ENUM(MAKE_ENUM)
};

#define MAKE_STRINGS(VAR) #VAR,
const char* const
RESOLUTION_NAMES[] =
{
    SOME_ENUM(MAKE_STRINGS)
};



const char *
GET_RESOLUTION_NAME(RESOLUTIONS type)
{
    return RESOLUTION_NAMES[static_cast<int>(type)];
}

int
GET_RESOLUTION_VALUE(RESOLUTIONS type)
{
    return static_cast<int>(type);
}

RESOLUTIONS
GET_RESOLUTION(int i)
{
    return static_cast<RESOLUTIONS>(i);
}



using namespace std;



int main(){


    printf("\nPlease enter the resolution you wish to use now by entering a number");

    printf("\n480p[0], 600p[1], 720p[2], 1080p[3]");

    int res_type;

    cin >> res_type;


    RESOLUTIONS selected_res = GET_RESOLUTION(res_type);

    printf("\nThe resolution you have selected is %s\n\n", GET_RESOLUTION_NAME(selected_res));

    return 0;

}

很抱歉没有提供解释,因为我现在必须走了。这个代码示例可以在这里找到。该代码适用于c++11并且可以编译通过。


1
呃,恶心的宏黑科技,我认为std::map解决方案更好。 - paulm
我同意,这看起来不太好。除了宏之外,它还有随机的空格和很多大写字母锁定键。对于这样一个简单的问题来说,这也是很多代码。 - jplatte
2
事实上,它看起来不太“漂亮”或者使用了大写字母,并不意味着它是无效的答案。它是其他答案的一种替代方案。 - Marcin

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