istream clear() не работает (не сбрасывает failbit)
От: Astral29 Эстония  
Дата: 09.06.07 15:52
Оценка:
Здравствуйте.

Не подскажете, почему failbit не сбрасывается? Вот пример кода:


#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    int ival;

    while (cin >> ival, !cin.eof())
    {
        if (cin.bad())
            throw runtime_error("istream corrupted.");
        if (cin.fail())
        {
            cout << "wrong data. enter again\n";
            cin.clear(istream::failbit);
            continue;
        }

        cout << "Your number is: " << ival << endl;
    }

    system("PAUSE");
    return EXIT_SUCCESS;
}


Если вводишь не число, а например слово (букву), то выставляется failbit, а вот сбрасываться он
никак не хочет. Что я делаю не так? Вроде всё верно. Проверялось на MS VStudio Express 2005.

Заранее спасибо.
Re: istream clear() не работает (не сбрасывает failbit)
От: Alex Alexandrov США  
Дата: 09.06.07 16:33
Оценка:
Здравствуйте, Astral29, Вы писали:

A>Здравствуйте.


A>Если вводишь не число, а например слово (букву), то выставляется failbit, а вот сбрасываться он

A>никак не хочет. Что я делаю не так? Вроде всё верно. Проверялось на MS VStudio Express 2005.

A>Заранее спасибо.


void clear(
iostate _State=goodbit
);

Parameter_State (optional)
The flags you want to set after clearing all flags.


Наверное, тебе нужно просто clear().
It's kind of fun to do the impossible (Walt Disney)
Re[2]: istream clear() не работает (не сбрасывает failbit)
От: Astral29 Эстония  
Дата: 09.06.07 16:39
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Здравствуйте, Astral29, Вы писали:


A>>Здравствуйте.


A>>Если вводишь не число, а например слово (букву), то выставляется failbit, а вот сбрасываться он

A>>никак не хочет. Что я делаю не так? Вроде всё верно. Проверялось на MS VStudio Express 2005.

A>>Заранее спасибо.


AA>

AA>void clear(
AA> iostate _State=goodbit
AA>);

AA>Parameter_State (optional)
AA>The flags you want to set after clearing all flags.


AA>Наверное, тебе нужно просто clear().


Неа, я и так и сяк пробывал. Не работает
Re[3]: istream clear() не работает (не сбрасывает failbit)
От: Хитрик Денис Россия RSDN
Дата: 09.06.07 17:44
Оценка: +1
Здравствуйте, Astral29, Вы писали:

AA>>Наверное, тебе нужно просто clear().

A>Неа, я и так и сяк пробывал. Не работает

Нет, нужно именно просто cin.clear(). В том коде, что ты показал ты его не сбрасываешь, а сам повторно устанавливаешь.

Вообще же твоя проблема заключалась в том, что ты хотя и сбрасывал failbit, но не изменял содержимое потока! Неудавшаяся операция чтения целого числа не удаляет некорректные с её точки зрения символы из потока. Поэтому у тебя программа входила в бесконечный цикл: в потоке есть некорректные данные -> пытаемся прочитать их как чило -> исключение -> сбрасываем failbit -> снова считываем некорректные данные (те же самые!). Вот и всё.

Следовательно, в случае ошибки нужно очистить поток ввода, чтобы вводимые тобой символы попадали в чистый поток. А это можно сделать следующим образом:
    ... 
    if (cin.fail())
    {
        cout << "wrong data. enter again\n";
       cin.clear();
       cin.ignore(static_cast<streamsize>(numeric_limits<int>::max()), '\n');
        continue;
    }
    ...


Функция ignore у всех потоков ввода позволяет игнорировать всё текущее содержимое до тех пор, пока не встретится символ, передаваемый вторым параметром, но не более чем количество символов, указанное первым параметром.
В нашем случае символ — перевод строки.

Скобки забыл поставить после max — это функция! ДХ
Правила нашего с вами форума.
Как правильно задавать вопросы. © 2001 by Eric S. Raymond; перевод: © 2002 Валерий Кравчук.
Re[4]: istream clear() не работает (не сбрасывает failbit)
От: Хитрик Денис Россия RSDN
Дата: 09.06.07 17:50
Оценка:
Собственно, знания получены с RSDN
Смотри http://rsdn.ru/Forum/?mid=374358
Автор: Павел Кузнецов
Дата: 04.09.03
.
Правила нашего с вами форума.
Как правильно задавать вопросы. © 2001 by Eric S. Raymond; перевод: © 2002 Валерий Кравчук.
Re[4]: istream clear() не работает (не сбрасывает failbit)
От: Хитрик Денис Россия RSDN
Дата: 09.06.07 18:09
Оценка:
Здравствуйте, Хитрик Денис, Вы писали:

Прошу прощения, забыл скобки после max:

    ... 
       cin.ignore(static_cast<streamsize>(numeric_limits<int>::max()), '\n');
    ...
Правила нашего с вами форума.
Как правильно задавать вопросы. © 2001 by Eric S. Raymond; перевод: © 2002 Валерий Кравчук.
Re[4]: istream clear() не работает (не сбрасывает failbit)
От: Astral29 Эстония  
Дата: 10.06.07 06:57
Оценка:
Здравствуйте, Хитрик Денис, Вы писали:

ХД>Нет, нужно именно просто cin.clear(). В том коде, что ты показал ты его не сбрасываешь, а сам повторно устанавливаешь.


Это, кстати, практически пример из книги "C++ Вводный курс, 4е издание" С.Липпман
Там ничего про ignore нет.

ХД>Вообще же твоя проблема заключалась в том, что ты хотя и сбрасывал failbit, но не изменял содержимое потока! Неудавшаяся операция чтения целого числа не удаляет некорректные с её точки зрения символы из потока. Поэтому у тебя программа входила в бесконечный цикл: в потоке есть некорректные данные -> пытаемся прочитать их как чило -> исключение -> сбрасываем failbit -> снова считываем некорректные данные (те же самые!). Вот и всё.


ХД>Следовательно, в случае ошибки нужно очистить поток ввода, чтобы вводимые тобой символы попадали в чистый поток. А это можно сделать следующим образом:

ХД>
ХД>    ... 
ХД>    if (cin.fail())
ХД>    {
ХД>        cout << "wrong data. enter again\n";
ХД>       cin.clear();
ХД>       cin.ignore(static_cast<streamsize>(numeric_limits<int>::max()), '\n');
ХД>        continue;
ХД>    }
ХД>    ... 
ХД>


ХД>Функция ignore у всех потоков ввода позволяет игнорировать всё текущее содержимое до тех пор, пока не встретится символ, передаваемый вторым параметром, но не более чем количество символов, указанное первым параметром.

ХД>В нашем случае символ — перевод строки.

Большое спасибо за ответ.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.