Вход в меню: после обнаружения неверного ввода все входы считаются недействительными - PullRequest
0 голосов
/ 09 мая 2019

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

Если число введено правильно,все отлично работаетЕсли введен неправильный ввод (строка, число с плавающей запятой, отрицательное число и т. Д.), Ничего не произойдет, если предполагается отобразить сообщение об ошибке.

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

Это цикл, который я использую для проверки кода -

bool check = false;
string line;
std::stringstream temp;
int input;

while(!check)
{
    getline(cin, line);
    temp << line;
    temp >> std::noskipws >> input; //this is supposed to reject spaces and floats

    if(!temp.fail() && temp.eof() && input > 0 && input <= static_cast<int>(options.size()))
    {
        check = true; //returns valid value and stops loop
    }
    else //if all conditions aren't met
    {
        cin.clear();
        cin.ignore();
        cout << wrongInput << endl; //prints error
    }
}
return input; //correctly returns when valid on first try

Перед этим,Я просто использовал cin >> input и cin.fail () для проверки, но это позволило проходить числам с плавающей точкой и отображать сообщение об ошибке несколько раз для строковых записей.

Если есть какая-либо пропущенная информация, пожалуйста, дайте мне знать,но я думаю, что здесь все, что имеет значение.


РЕДАКТИРОВАТЬ: просто тестировал мою программу с только правильными вводами, и она, казалось бы, начала произвольно давать сбой.

Пример неправильного ввода:

(menu with numbered options)
intput: "abba" || "3.2" || "4 3" || "-4" || etc.
(no response)
input: "valid number"
(please enter a number from above) - repeats indefinitely

Пример правильного ввода:

(menu with numbered options)
input: "1"
(correctly executes "1" selection, shows menu again)
input: "1"
(again correctly executes "1" selection, shows menu again)
input: "1"
(no response)
input: "1"
(please enter a number from above) - repeats indefinitely

1 Ответ

0 голосов
/ 09 мая 2019

Есть некоторые проблемы с кодом, который вы показываете.Начнем с того, что вы не проверяете статус чтения с std::cin.Если произошел сбой или пользователь нажал последовательность конца файла, вы ее не обнаружите.

Во-вторых, нет необходимости сбрасывать флаги std::cin, и определенно нет необходимости ignore любой ввод от std::cin либо.

В-третьих, как я уже говорил, флаг eof будет не установлен в потоке строки temp.И есть лучший способ проверить наличие флагов ошибок или eof.

В-четвертых, если вы не хотите использовать отрицательные числа, используйте целочисленный тип unsigned , и извлечение потока будетпотерпеть неудачу, если он отрицательный.

Наконец, и это скорее личное мнение, почему бы не позволить лидирующее место?В этом нет ничего плохого.

Учитывая все сказанное и сделанное, я бы сделал это примерно так:

unsigned input;

std::string line;
while (std::getline(std::cin, line))
{
    // Define stream inside the loop, no need to reset it when the loop iterates
    std::istringstream istr(line);

    // Attempt to extract the value, checking range
    if (istr >> input && input > 0 && input <= options.size())
    {
        // All went okay, the input is valid
        break;
    }

    // If we reach here, there was an error parsing the input
    // Or the input was out of bounds
    std::cout << wrongInput << '\n';
}

if (!std::cin)
{
    // Could not even read from standard input, consider this a fatal error
    return EXIT_FAILURE;
}

// Here the variable input contains a value that is larger than zero and smaller or equal to options.size()

Если вам нужно сделать это несколько раз, то яКонечно, рекомендуем вам поместить приведенный выше код в его собственную функцию, которую вы можете вызвать.Тогда, если произошел сбой, вы можете вернуть 0 вместо EXIT_FAILURE, чтобы указать на ошибку любого типа.

...