Неправильное приведение типа строки к unsigned int - PullRequest
2 голосов
/ 11 ноября 2010

У меня возникла досадная проблема с функцией C ++, которую я написал и целью которой является проверка пользовательского ввода. Функция читает вводимые пользователем данные, проверяет, является ли это число и, если да, находится ли оно в диапазоне [min, max].

Проблема возникает, когда я вызываю функцию шаблона с беззнаковым типом, таким как size_t, и ввод является отрицательным числом. Поток строк преобразует строку во что-то вроде 4294967291. Я вижу, что программа конвертирует данные в значение, близкое к значению de max для типа данных без знака (определенного в заголовке numeric_limits), но мой вопрос - почему, поскольку if оператор должен остановиться на sstream >> value?

Мой код:

template <class T>
T getNumberInput(std::string prompt, T min, T max) {
    std::string input;
    T value;

    while (true) {
        try {
            std::cout << prompt;
            std::cin.clear();
            std::getline(std::cin, input);
            std::stringstream sstream(input);

            if (input.empty()) {
                throw EmptyInput<std::string>(input);
            } else if (sstream >> value && value >= min && value <= max) {
                std::cout << std::endl;
                return value;
            } else {
                throw InvalidInput<std::string>(input);
            }
        } catch (EmptyInput<std::string> & emptyInput) {
            std::cout << "O campo não pode ser vazio!\n" << std::endl;
        } catch (InvalidInput<std::string> & invalidInput){
            std::cout << "Tipo de dados inválido!\n" << std::endl;
        }
    }
}

Спасибо за ваше время!

Ответы [ 2 ]

2 голосов
/ 11 ноября 2010

В арифметике C ++, включающей тип unsigned с битами значения n , гарантированно будет по модулю 2 ^ n .Это означает, что любой результат возвращается в диапазон от 0 до 2 ^ n -1, путем сложения или вычитания подходящего кратного 2 ^ n .Это также относится и к C.

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

Кстати, ваши if с >> и && оказал некоторое влияние на мой плохой кодометр.Я никогда не могу вспомнить предшествующие операторы для >> против &&.Я предполагаю, что если он скомпилирован, то все должно быть в порядке, поскольку >> не может принимать значение справа.Проверка ... ОК, но я бы использовал скобки, чтобы прояснить это.

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

Приветствия & hth.,

1 голос
/ 11 ноября 2010

Альф уже ответил на это, но у меня была пара других мыслей.Вытащите код, который получает ввод из блока try.Вы не поймете каких-либо исключений, которые он может выдать, поэтому он также не сообщает о намерении.Блок try должен начинаться прямо перед if (input.empty ()) ... Затем вытащить все элементы блока try в одну функцию проверки.Это очищает код здесь.Однако для использования в графическом интерфейсе вы хотели бы создать функцию, которая просто получает входные данные без проверки и предоставляет функцию проверки.Затем пользователь может обрабатывать исключения проверки по мере необходимости.Хотя в этом случае я не вижу преимущества использования исключений по сравнению с простыми кодами ошибок для проверки.

Надеюсь, это поможет,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...