c ++: только целое число cin

0

Я пытаюсь проверить входные данные с помощью блоков try-catch и столкнулся с небольшой проблемой.

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

Также, если при вводе int они вводят двойное значение (45.1), тогда программа принимает 45 как int (x) и 0,1 для double (y). Мне нужно, чтобы он либо выбросил ошибку, либо будет счастлив, если он просто округляет число до ближайшего целочисленного значения

Код:

int x;
double y, z;

while (1)
{
    try 
    {
        std::cout << "Enter an int (x): ";
        if (std::cin >> x && x > 0) { break; }
        else if (!std::cin) { throw x; }
        else { throw x; }
    }
    catch (int)
    {
        std::cout << "Error: Not a valid integer.\n\n";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

while (1)
{
    try
    {
        std::cout << "Enter a double (y): ";
        if (std::cin >> y && y > 0) { break; }  
        else if (!std::cin) { throw y; }
        else { throw y; }
    }
    catch (double)
    {
        std::cout << "Error: Not a valid double.\n\n";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

z = x + y;
std::cout << "\n\n" << x << " + " << y << " = " << z;
  • 2
    123abc напрямую преобразуется в 123, когда помещается в int из потока (по крайней мере, я перепроверил его с помощью stringstream)
  • 1
    да, ты прав, спасибо, только что проверил это. Также добавлены строки cin.clear () и cin.ignore () в исходную инструкцию if в обоих циклах, и теперь int округляется, если вводится как double, большое спасибо @Mayerz
Теги:
input
try-catch
cin

2 ответа

2

Я бы написал функцию, которая берет строку ввода, извлекает int из int и проверяет, не осталось ли другого мусора. Я использовал std::ws манипулятор, чтобы избавиться от отстающих пробелов, которые не должны быть ошибкой, IMO.

bool parse_int(int& i)
{
    std::string line;
    std::getline(std::cin, line);
    std::istringstream iss(line);
    return (iss >> i && (iss >> std::ws).peek() == EOF);
}

И затем используйте его как:

int i;
if ( parse_int(i) ) /* ok */

В качестве альтернативы, если вам не нужны избыточные данные, вы можете просто проигнорировать после того, как вы получите int, используя istream::ignore.

Кроме того, бросать арифметические типы странно. Некоторый подкласс std::logic_error исключения std::logic_error был бы более уместным.

  • 0
    @AbhishekBansal Да, спасибо.
  • 0
    Хороший способ сделать это, +1
0
int main()
{
 std::stringstream ss;
 int x;

 ss << "123abc";
 ss >> x;
 std::cout << x << std::endl; // 123 

 // And   

 ss << "abc123";
 ss >> x;
 std::cout << x << std::endl; // 0 

 return 0;
}

Поток обрабатывает каждый символ один за другим и останавливается для недопустимого caractere согласно заданному типу.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню