Форум программистов, компьютерный форум CyberForum.ru

Не удаётся сбросить ios::failbit - C++

Восстановить пароль Регистрация
 
Joe Rixans
0 / 0 / 0
Регистрация: 26.02.2014
Сообщений: 5
26.02.2014, 14:55     Не удаётся сбросить ios::failbit #1
Всем привет!
У меня вопрос следующего характера. Идущий ниже кусок кода работает не логично
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
list<int> lval;
vector<int> ivec;
int val=0;
cout<<"Введите целочисленные значения: ";
while (true)
{
    cin>>val;
    if (cin.bad())
    {
        cerr<<"Ошибка ввода/вывода. Поток недоступен"<<endl;
        cin.clear(ios::badbit);
        break;
    }
    if (cin.eof())
    {
        cerr<<"Ошибка ввода/вывода. Достигнут конец файла"<<endl;
        cin.clear(ios::eofbit);
        break;
    }
    if (cin.fail())
    {
        cerr<<"Ошибка ввода/вывода. Операция ввода/вывода закончилась неудачей"<<endl;
        cin.clear(ios::failbit);
        break;
    }
    lval.push_back(val);
}
cin.clear();
cout<<"Введите целочисленные значения: ";
while (true)
{
    cin>>val;
    if (cin.bad())
    {
        cerr<<"Ошибка ввода/вывода. Поток недоступен"<<endl;
        cin.clear(ios::badbit);
        break;
    }
    if (cin.eof())
    {
        cerr<<"Ошибка ввода/вывода. Достигнут конец файла"<<endl;
        cin.clear(ios::eofbit);
        break;
    }
    if (cin.fail())
    {
        cerr<<"Ошибка ввода/вывода. Операция ввода/вывода закончилась неудачей"<<endl;
        cin.clear(ios::failbit | ios::eofbit);
        break;
    }
    ivec.push_back(val);
}
По сути дела, здесь никаких ошибок компиляции нет, но есть некая непонятная мне особенность. При вводе цифр, как в следующем, примере выдаёт вот что.

Введите целочисленные значения: 98 98 484 6 ^Z 5 1265 64 652
Ошибка ввода/вывода. Операция ввода/вывода закончилась неудачей
Введите целочисленные значения: Ошибка ввода/вывода. Операция ввода/вывода закончилась неудачей


Выходит так, что lval вполне сносно заполняется, а ivec остаётся пустым.
А теперь вопрос: почему так происходит? Обратите внимание на то что между циклами умышленно ставиться cin.clear(), дабы заострить внимание на проблеме.

Добавлено через 3 часа 37 минут
Я не понимаю, 20 человек посмотрело и ни у кого ни какой идеи не возникло? Или это настолько сложно, что не по адресу?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.02.2014, 15:17     Не удаётся сбросить ios::failbit #2
Если поток ломается, то cin.clear() недостаточно. То что не ввелось остаётся в очереди ввода, и её нужно очистить. Например, так:
C++
1
2
cin.clear();
while (cin.get() != '\n');
zss
Модератор
Эксперт С++
 Аватар для zss
5943 / 5548 / 1783
Регистрация: 18.12.2011
Сообщений: 14,171
Завершенные тесты: 1
26.02.2014, 15:18     Не удаётся сбросить ios::failbit #3
все получается правильно, если после ввода первой серии ввести Enter
и только после этого нажать ^Z
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
26.02.2014, 17:09     Не удаётся сбросить ios::failbit #4
C++
1
2
3
4
5
cin.clear(ios::badbit);
...
cin.clear(ios::eofbit);
...
cin.clear(ios::failbit);
мне интересно, вы правда понимаете что делают тут ваши clear?
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
26.02.2014, 18:42     Не удаётся сбросить ios::failbit #5
А мне интересно, о чём думали те, кто выбрали для этого название "clear"...
Joe Rixans
0 / 0 / 0
Регистрация: 26.02.2014
Сообщений: 5
26.02.2014, 22:49  [ТС]     Не удаётся сбросить ios::failbit #6
метод clear по идеи и должен восстанавливать состояние потока до корректного. о том что необходимо "обойти" символ, я думал, но не догадался как.

Добавлено через 1 минуту
Цитата Сообщение от alsav22 Посмотреть сообщение
Если поток ломается, то cin.clear() недостаточно. То что не ввелось остаётся в очереди ввода, и её нужно очистить. Например, так:
C++
1
2
cin.clear();
while (cin.get() != '\n');
метод clear по идеи и должен восстанавливать состояние потока до корректного. о том что необходимо "обойти" символ, я думал, но не догадался как.

Добавлено через 1 минуту
Цитата Сообщение от zss Посмотреть сообщение
все получается правильно, если после ввода первой серии ввести Enter
и только после этого нажать ^Z
а по каким правилам это происходит, вы мне сможете объяснить? почему же первый ^Z не выкидывет eofbit, а только failbit. только не говорите мне, что в переменную типа int не удалось прочитать символ, это и так понятно
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.02.2014, 22:54     Не удаётся сбросить ios::failbit #7
Цитата Сообщение от Joe Rixans Посмотреть сообщение
clear по идеи и должен восстанавливать состояние потока до корректного
Это если он без аргументов. Если с аргументом, то этот флаг как раз установится, а другие будут сброшены.

Добавлено через 3 минуты
Цитата Сообщение от Joe Rixans Посмотреть сообщение
о том что необходимо "обойти" символ, я думал, но не догадался как.
Если в этой строке: 98 98 484 6 ^Z 5 1265 64 652, то:
C++
1
2
3
cin.clear();
cin.get();
cin.get();
Joe Rixans
0 / 0 / 0
Регистрация: 26.02.2014
Сообщений: 5
26.02.2014, 23:23  [ТС]     Не удаётся сбросить ios::failbit #8
Цитата Сообщение от retmas Посмотреть сообщение
C++
1
2
3
4
5
cin.clear(ios::badbit);
...
cin.clear(ios::eofbit);
...
cin.clear(ios::failbit);
мне интересно, вы правда понимаете что делают тут ваши clear?
я вполне, а вы? clear без аргументов выставляет все флаги в допустимое состояние, кроме _Hardfail. в качестве аргументов принимает флаги состояние потока, которые выставляет в допустимое состояние. если хотите можно реализовать через setstate, которая является аналогом.
зачем я тут сделал 3 проверки спросите вы, если можно обойтись проверкой значения метода good() потока? чтобы наглядно показать, что не реагируют на ^Z операторы потока, а реагируют в первую очередь на разность типов. напомню, что failbit выставляется и тогда, когда поток достиг конца.

Добавлено через 11 минут
Цитата Сообщение от alsav22 Посмотреть сообщение
Это если он без аргументов. Если с аргументом, то этот флаг как раз установится, а другие будут сброшены.
Вы не путаете с методом setstate? Специально залез в Страуструпа
void clear [iostate f= goodbit) ; //установить флаги состояния i/o , где goodbit==0

Добавлено через 1 минуту
Цитата Сообщение от alsav22 Посмотреть сообщение
Если в этой строке: 98 98 484 6 ^Z 5 1265 64 652, то:
C++
1
2
3
cin.clear();
cin.get();
cin.get();
Я понял вашу идею, но мне всё равно не понятно, почему не удаётся сбросить флаги в ручную? Флаги устанавливаются при чтении из потока, Но, когда я уже прочитал конец файл, почему флаги не сбрасываются? Да, я понимаю, что поток по сути "остановился" на eof, но не логичнее было бы сбросить флаги и продолжить чтение потока, а не обходить get() неугодные символы?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.02.2014, 23:43     Не удаётся сбросить ios::failbit #9
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Joe Rixans Посмотреть сообщение
Вы не путаете с методом setstate?
Не путаю.
Цитата Сообщение от Joe Rixans Посмотреть сообщение
cin.clear(ios::badbit);
Тут badbit устанавливается, а два других флага сбрасываются. setstate устанвливает флаг парамера, другие не трогает.

Добавлено через 6 минут
Цитата Сообщение от Joe Rixans Посмотреть сообщение
Да, я понимаю, что поток по сути "остановился" на eof, но не логичнее было бы сбросить флаги и продолжить чтение потока, а не обходить get() неугодные символы?
Флаги сбросили, а символы (не цифры) остались в потоке. Следующий cin ждёт цифры, получает не цифры, опять устанвливается флаг ошибки.

Добавлено через 6 минут
Цитата Сообщение от Joe Rixans Посмотреть сообщение
Да, я понимаю, что поток по сути "остановился" на eof
В данном случае, ^Z в середине строки - это не EOF.

Добавлено через 5 минут
Вот тут тема насчёт EOF в консоли: Флаг eofbit в потоке и условные операторы
Joe Rixans
0 / 0 / 0
Регистрация: 26.02.2014
Сообщений: 5
26.02.2014, 23:53  [ТС]     Не удаётся сбросить ios::failbit #10
Благодарствую. Вполне исчерпывающе, всё свои ошибки разобрал и понял. Есть еще один вопрос: то есть поток не будет переводиться в состояние конца, пока не будет введён enter в консоли?Т.е. все eof до '/n' будут рассматриваться системой как неправильный ввод данных?
P.S. Разбирал флаги потока по Липпману. 4 издание по С++. тарабарщины типа: cin.clear(ios::failbit); понабрался от туда)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.02.2014, 00:07     Не удаётся сбросить ios::failbit
Еще ссылки по теме:

Разница между ios::ate и ios::app C++
Как установить Failbit? C++
Ios::ate и ios::app C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.02.2014, 00:07     Не удаётся сбросить ios::failbit #11
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Joe Rixans Посмотреть сообщение
Есть еще один вопрос: то есть поток не будет переводиться в состояние конца, пока не будет введён enter в консоли?Т.е. все eof до '/n' будут рассматриваться системой как неправильный ввод данных?
Вот такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
int n;
    while (true)
    {
        cin >> n;
        cout << cin.bad() << endl;
        cout << cin.fail() << endl;
        cout << cin.eof() << endl << endl;
 
        if (cin.fail()) 
            break;
    }
Попробуйте строки чисел вводить. Флаг EOF установится только если ^Z будет первым в строке, и не важно, что за ним будут ещё символы в потоке. Дело в том, сто EOF в консоли - это не то, что EOF в файле. В файле - это признак того, что данных в файле больше нет (размер файла известен до чтения). В консоли неизвестно сколько символов будет введено, поэтому здесь EOF просто генерируется, нажатием определённых клавиш, и обрабатывется определённым образом (должен быть первым при вводе).
Yandex
Объявления
27.02.2014, 00:07     Не удаётся сбросить ios::failbit
Ответ Создать тему
Опции темы

Текущее время: 13:52. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru