C++ Проверка целого числа.

Новичок в С++. Возникли проблемы с правильным зацикливанием при обработке ошибок. Я пытаюсь проверить, является ли пользовательский ввод целым числом и положительным.

do{
    cout << "Please enter an integer.";
    cin >> n;

    if (cin.good())
    {
        if (n < 0) {cout << "Negative.";}
        else {cout << "Positive.";}
    }
    else
    {
        cout << "Not an integer.";
        cin.clear();
        cin.ignore();
    }
}while (!cin.good() || n < 0);

cout << "\ndone.";

При вводе нецелого числа цикл прерывается. Я чувствую, что неправильно понимаю неотъемлемое использование cin.clear() и cin.ignore() и статус cin во время этого цикла. Если я уберу cin.ignore(), цикл станет бесконечным. Почему это? Что я могу сделать, чтобы превратить это в элегантно функционирующий цикл? Спасибо.


person xavi    schedule 02.09.2013    source источник


Ответы (2)


В вашей нецелочисленной ветке вы вызываете дополнительные методы cin, поэтому cin.good() сбрасывается в true.

Вы можете изменить свой код примерно так:

while(1) { // <<< loop "forever"
    cout << "Please enter an integer.";
    cin >> n;

    if (cin.good())
    {
        if (n < 0) {cout << "Negative.";}
        else { cout << "Positive."; break; }
    }                            // ^^^^^ break out of loop only if valid +ve integer
    else
    {
        cout << "Not an integer.";
        cin.clear();
        cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
    }
}

cout << "\ndone.";

или вы можете упростить его еще больше, например:

while (!(cin >> n) || n < 0) // <<< note use of "short circuit" logical operation here
{
    cout << "Bad input - try again: ";
    cin.clear();
    cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
}

cout << "\ndone.";
person Paul R    schedule 02.09.2013
comment
Это работает фантастически, спасибо! Я даже не думал, что мой выбор петли меня сдерживает. Я ценю помощь и объяснение. - person xavi; 02.09.2013
comment
Не приведет ли вторая версия к бесконечному циклу, когда пользователь введет мусор (т.е. что-то вроде abc)? Вам нужно извлечь (или игнорировать) мусор перед циклом (но после clear()). - person James Kanze; 02.09.2013
comment
@James: хороший улов - спасибо - я это исправил (и даже проверил!). - person Paul R; 02.09.2013

int n;

while (!(cin >> n)||n<0)//as long as the number entered is not an int or negative, keep checking
{
cout << "Wrong input. Please, try again: ";
cin.clear();//clear input buffer

}
//only gets executed when you've broken out of the while loop, so n must be an int
cout << "Positive.";

cout << "\ndone.";//finished!

Должен делать то, что ты хочешь.

person imulsion    schedule 02.09.2013
comment
теперь, когда я его изучаю, он даже не делает того, о чем он просил. если вход хороший, вы должны уйти, только если он отрицательный... - person No Idea For Name; 02.09.2013
comment
@NoIdeaForName извините, не заметил. спасибо за улов :) - person imulsion; 02.09.2013
comment
Если введено нецелое число, этот цикл станет бесконечным. Делает то же самое, что и мой цикл. - person xavi; 02.09.2013
comment
Он всегда ломается после ввода целого числа. Исходный код должен прерываться только в том случае, если введено отрицательное целое число. - person Onur; 02.09.2013
comment
Я считаю, что он должен сломаться только в том случае, если введено положительное целое число (›= 0). - person Paul R; 02.09.2013
comment
cin.clear() очищает флаги ошибок, но не очищает входной буфер - person M.M; 13.06.2019