简体   繁体   English

使用 C++ 进行枚举(输入检查)

[英]Enum with c++ (Input checking)

I am new in C++ and came up with the idea of writing "a short quiz" to use "enum" and have a clearer understanding of how it works.我是 C++ 新手,想出了编写“简短测验”以使用“枚举”的想法,并对它的工作原理有更清晰的了解。 My idea consists in displaying three options to the user, and the he/she would have to introduce the number that corresponds to the correct option.我的想法是向用户显示三个选项,他/她必须介绍与正确选项相对应的数字。 This depicts the situation:这描述了这种情况:

# include <iostream>

int main(){

    std::cout << "Which one is the capital of Ireland?";
    std::cout << "\n1-Barcelona\n2-Frankfurt\n3-Dublin\n";
    std::cout << "Please introduce the number of the correct option";

    enum question {barcelona=1,frankfurt=2,dublin=3};

    int iAnswer;
    std::cin >> iAnswer;

    question eAnswer= static_cast<question>(iAnswer);

The problem with this code is that after casting the integer introduced by the user (iAnswer), there's no error message/warning when such number does not exist in the "question" data type options.此代码的问题在于,在转换用户引入的整数 (iAnswer) 后,当“问题”数据类型选项中不存在此类数字时,不会出现错误消息/警告。 In other words;换句话说; if the user introduced 100, after casting iAnswer we could see that there's no option related to 100 since the only accepted values are 1,2 and 3. The question would be then... how could I check that the number the user introduces does exist in my enum options?如果用户引入了 100,在转换 iAnswer 之后,我们可以看到没有与 100 相关的选项,因为唯一接受的值是 1,2 和 3。那么问题将是......我如何检查用户引入的数字是否正确存在于我的枚举选项中吗? why casting doesn't show any error when in theoretically the casting couldn't be successfully done?为什么在理论上铸造无法成功完成时,铸造没有显示任何错误?

Thanks!!谢谢!!

Does this help to understand?这有助于理解吗? https://en.cppreference.com/w/cpp/language/enum https://en.cppreference.com/w/cpp/language/enum

Values of integer, floating-point, and enumeration types can be converted by static_cast or explicit cast, to any enumeration type.整数、浮点和枚举类型的值可以通过 static_cast 或显式强制转换转换为任何枚举类型。 If the underlying type is not fixed and the source value is out of range, the result is unspecified (until C++17)undefined (since C++17).如果基础类型不固定且源值超出范围,则结果为 unspecified (C++17 前)undefined (C++17 起)。 (The source value, as converted to the enumeration's underlying type if floating-point, is in range if it would fit in the smallest bit field large enough to hold all enumerators of the target enumeration.) Otherwise, the result is the same as the result of implicit conversion to the underlying type. (源值,如果是浮点数,则转换为枚举的基础类型,如果它适合容纳目标枚举的所有枚举器的最小位字段,则它在范围内。)否则,结果与隐式转换为基础类型的结果。

Note that the value after such conversion may not necessarily equal any of the named enumerators defined for the enumeration.请注意,此类转换后的值可能不一定等于为枚举定义的任何命名枚举器。

To solve the problem of checking the user input, you could it with something like this:要解决检查用户输入的问题,您可以使用以下方法:

    question getEnumAnswerFromInteger(int iAnswer)
    {
       if (iAnswer >= 1 && iAnswer <= 3)
       {
           return static_cast<question>(iAnswer);
       }
       else { /* throw some exception... */ }
    }

Also, consider using enum class instead of just enum .另外,请考虑使用enum class而不仅仅是enum And then using the proper scope do address the values.然后使用适当的范围来解决这些值。

As others have already pointed out, static_cast simply converts an int to Enum, it doesn't verify.正如其他人已经指出的那样, static_cast只是将 int 转换为 Enum,它不进行验证。

Please find my own solution for simple range checked enum(enums that have contiguous values).请为简单的范围检查枚举(具有连续值的枚举)找到我自己的解决方案。 It uses scoped enums which are much safer and will work for your case.它使用更安全的范围枚举,并且适用于您的情况。

#include <iostream>
#include <exception>
#include <type_traits>

template <typename E>
auto safe_cast_enum_in_range(typename std::underlying_type<E>::type val, E min, E max) {
  if (val < static_cast<decltype(val)>(min) || val > static_cast<decltype(val)>(max)) {
    throw std::out_of_range("oor");
  }
  return static_cast<E>(val);
}

int main() {
  enum class E1{k1, k2, k3};
  try {
    auto x = safe_cast_enum_in_range(2, E1::k1, E1::k3); // no exception
    auto y = safe_cast_enum_in_range(4, E1::k1, E1::k3); // exception
  } catch (...) {
    std::cout << "Exception\n";
  }
}

The question would be then... how could I check that the number the user introduces does exist in my enum options?那么问题是……我如何检查用户引入的数字是否存在于我的枚举选项中?

You have to make a function to validate and map the integer to an enum:您必须创建一个函数来验证整数并将其映射到枚举:

enum class Question
{
    invalid   = 0,
    barcelona = 1,
    frankfurt = 2,
    dublin    = 3
};

Question map_to_question_enum(int answer)
{
    switch (answer)
    {
        case 1:
            return Question::barcelona;

        case 2:
            return Question::frankfurt;

        case 3:
            return Question::dublin;

        default:
            return Question::invalid;
    };
}

Used like:像这样使用:

int answer;
std::cin >> answer;

Question question_answer = map_to_question_enum(answer);

if (question_answer == Question::invalid)
     ...
else 
     ...

why casting doesn't show any error when in theoretically the casting couldn't be successfully done?为什么在理论上铸造无法成功完成时,铸造没有显示任何错误?

Because static_cast only converts an integer into the enum .因为static_cast只将整数转换为enum By it's definition it does not verify .根据它的定义,它不会验证.

Most probably the question during verification would be: what to do in the case of an invalid value?验证过程中最有可能的问题是:在无效值的情况下该怎么办?

  • throw an exception?抛出异常? (sometimes exceptions are not allowed) (有时不允许例外)
  • convert to an error value?转换为错误值? (which value symbolizes an error?) (哪个值象征错误?)
  • is the error from the enum list or from the different area?错误是来自枚举列表还是来自不同区域?
  • ... ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM