Перечисление с C ++ (проверка ввода) - PullRequest
0 голосов
/ 11 февраля 2020

Я новичок в C ++, и мне пришла в голову идея написать «короткий тест», чтобы использовать «enum» и иметь более четкое представление о том, как он работает. Моя идея состоит в том, чтобы показать пользователю три варианта, и он / она должен будет ввести число, соответствующее правильному варианту. Это изображает ситуацию:

# 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);

Проблема с этим кодом состоит в том, что после приведения целого числа, введенного пользователем (iAnswer), нет сообщения об ошибке / предупреждения, когда такого числа не существует в «вопросе» параметры типа данных. Другими словами; если бы пользователь ввел 100, после приведения iAnswer мы могли бы видеть, что нет никакой опции, связанной с 100, поскольку единственные допустимые значения - 1,2 и 3. Тогда возникает вопрос ... как я могу проверить, что число, введенное пользователем, делает существуют в моих вариантах enum? почему кастинг не показывает ошибку, когда теоретически кастинг не может быть успешно выполнен?

Спасибо !!

Ответы [ 3 ]

1 голос
/ 11 февраля 2020

Как уже отмечали другие, static_cast просто конвертирует int в Enum, но не проверяет.

Пожалуйста, найдите мое собственное решение для простого перечисления enum с проверкой диапазона (перечисления, которые имеют смежные значения). Он использует ограниченные перечисления, которые намного безопаснее и будут работать для вашего случая.

#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";
  }
}
1 голос
/ 11 февраля 2020

Помогает ли это понять? https://en.cppreference.com/w/cpp/language/enum

Значения целочисленного типа, типа с плавающей точкой и перечисления могут быть преобразованы с помощью static_cast или явного преобразования в любой тип перечисления. Если базовый тип не является фиксированным, а исходное значение выходит за пределы диапазона, результат не определен (до C ++ 17) и не определен (начиная с C ++ 17). (Исходное значение, преобразованное в базовый тип перечисления, если с плавающей точкой, находится в диапазоне, если оно поместится в поле наименьшего бита, достаточно большое, чтобы вместить все перечислители целевого перечисления.) В противном случае результат совпадает с результат неявного преобразования в базовый тип.

Обратите внимание, что значение после такого преобразования может не обязательно равняться любому из именованных перечислителей, определенных для перечисления.

Для решения проблемы проверяя пользовательский ввод, вы можете сделать это примерно так:

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

Также рассмотрите возможность использования enum class вместо просто enum. А затем, используя правильную область видимости, адресуйте значения.

0 голосов
/ 11 февраля 2020

Тогда возникает вопрос ... как я могу проверить, что число, введенное пользователем, существует в моих параметрах 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;
    };
}

Используется как:

int answer;
std::cin >> answer;

Question question_answer = map_to_question_enum(answer);

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

почему Приведение не показывает никаких ошибок, когда теоретически приведение не может быть успешно выполнено?

Поскольку static_cast преобразует только целое число в enum. По определению он не проверяет .

Скорее всего, вопрос во время проверки будет таким: что делать в случае недопустимого значения?

  • бросить исключение? (иногда исключения не допускаются)
  • преобразовать в значение ошибки? (какое значение символизирует ошибку?)
  • это ошибка из списка enum или из другой области?
  • ...
...