Не могу cin после завершения цикла while

int n;
while(cin>>n)
    cout << n; // Run by the program if received an int value
cout << "Break from loop"; // Run by the program
cin >> n; // Skipped by the program
cout << n; // Run by the program

не могу принять другой ввод после завершения цикла while с использованием символов.

Как принять другой ввод, если ввод в цикле был завершен с использованием нецелых значений/значений с плавающей запятой.


person user3317046    schedule 16.02.2014    source источник
comment
Это правильное наблюдение.   -  person Kerrek SB    schedule 17.02.2014
comment
В чем именно заключается ваш вопрос?   -  person Josh Braun    schedule 17.02.2014
comment
Кто-нибудь знает более чистый способ, чем cin.clear(); getline(cin,dummystring);?   -  person Beta    schedule 17.02.2014
comment
@Beta Серьезный вопрос?   -  person 0x499602D2    schedule 17.02.2014
comment
@ 0x499602D2: Да, с оттенком насмешки над пользователем, который не может найти reset cin.   -  person Beta    schedule 17.02.2014
comment
@Beta Ну, лучшим способом было бы использовать ignore() для отбрасывания символов std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'), но нет, нет более чистого способа сделать это. Однако вы можете поместить очистку внутри функции.   -  person 0x499602D2    schedule 17.02.2014


Ответы (2)


Если вы не завершаете программу, возвращая конец файла (например, Ctrl-D), или полностью завершаете программу (например, Ctrl-C).

То есть, если вы выходите из цикла с неправильным типом данных, например, вводя букву d вместо целого числа, вы можете следовать циклу while с cin.clear() и getline(cin, str), где str — это какое-то string, которое вы объявили заранее.

После этого вы сможете принять ввод для второго cin.

So,

string str;
int n;
while(cin>>n)
    cout << n << endl;
cin.clear();
getline(cin, str);
cout << "Break from loop" << endl;;
cin >> n;
cout << n;
person Mars    schedule 16.02.2014
comment
Ух ты! это просто отлично работает. Спасибо! - person user3317046; 17.02.2014

Предполагая, что ваш вопрос: «Как возобновить ввод после установки состояния потока?» тогда есть простое объяснение:

Цикл while, в котором вы выполняли извлечение, прерывался только до тех пор, пока извлечение не завершилось неудачей; это также включает в себя, когда поток достигает конца входного потока (EOF). Когда это произойдет, eofbit будет установлен в состояние пара (так же, как и failbit). Поток нельзя использовать для ввода-вывода, если установлено его состояние потока. Чтобы использовать его снова, состояние потока должно быть очищено. Это делается с помощью функции-члена clear(std::ios_base::iostate err = std::ios_base::goodbit).

std::cin.clear();

Этот вызов очистит биты в состоянии потока и назначит их 0 (std::ios_base::goodbit). После этого вызова поток снова можно использовать для ввода/вывода.

Это предполагает, что поток считывает все символы, пока не достигнет EOF. Этого недостаточно для предыдущего чтения, которое завершилось при получении неверных данных. Также нужно было бы ignore() остальных символов.

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
person 0x499602D2    schedule 16.02.2014
comment
Это не работает для меня без дополнительного шага для очистки плохих символов. Вы уверены, что этого достаточно? - person Beta; 17.02.2014
comment
@Beta Предполагается, что поток считывает все символы, пока не достигнет EOF. Этого недостаточно для предыдущего чтения, которое завершилось при получении неверных данных. Нужно было бы ignore() остаточные данные. - person 0x499602D2; 17.02.2014
comment
да, это мой вопрос, извините, что не уточнил. однако я все еще нуб, поэтому я не понимаю технических особенностей С++. - person user3317046; 17.02.2014
comment
@user3317046 user3317046 Пожалуйста, смотрите правку. - person 0x499602D2; 17.02.2014