Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > cin принимает только цифры


Автор: Negent 22.6.2014, 11:13
Доброго времени суток!
Написал программу, которая считывает и выводит элементы массива... Всё просто, но на самом деле, мне бы чуть больше понимания, как работает кусок кода (программа рабочая).
Код:
Цитата

//Эта программа добивается ввода чисел, вместо всякой ерунды
#include <iostream>
#include "stdafx.h"
using namespace std;

void main ()
{
    int Ar[5];
    int value;
    for (int i=0; i<5; i++)
    {
  cout<<"Ar["<<i+1<<"]: ";
  cin>>value;
  while (!cin)
  {
    cout<<"Enter again A["<<i+1<<"]: ";
    cin.clear ();
    while (cin.get ()!= '\n') continue;
    cin>>value;
  }
  Ar[i] = value;
    }
    cout<<"Exit!"<<endl;
    for (int i=0; i<5; i++)
    cout<<"A["<<i+1<<"]: "<<Ar[i]<<endl;
    system ("pause");
}


А именно, вот этот кусок:
Цитата
for (int i=0; i<5; i++)
    {
  cout<<"Ar["<<i+1<<"]: ";
  cin>>value;
  while (!cin)
  {
    cin.clear ();
    while (cin.get ()!= '\n') continue;
    cout<<"Enter again A["<<i+1<<"]: ";
    cin>>value;
  }
  Ar[i] = value;
    }


Проверьте пожалуйста, ход рассуждений (только это, переписывать ничего не надо в коде!):
1. Ввод значения во временную переменную "value".
2. Если введённое значение не подходит, то в очереди потока в cin, выставляется флаг, имеющий значение "ложь", что даёт запуск цикла "while". (истина = не-ложь)
3. Цикл "while (!cin)" операторами в теле цикла: cin.clear() очищает очередь символов , а while (cin.get()) выполняет сброс символа новой строки столько раз, пока они там есть. Continue выполняет новую и новую итерацию, пока там ещё есть символы новой строки. Сам cin.clear () не может выполнить очистку на символы новой строки.
4. Производится считывание временной переменной "value", если оно истинно, т.е. введено корректное значение (число), то флаг в условии цикла while (!cin) равен "истина".
5. Число присваивается элементу массива. При наличии корректного ввода, происходит выполнение цикла for (), без циклов while() 

Автор: NoviceF 23.6.2014, 12:44
Цитата(Negent @  22.6.2014,  12:13 Найти цитируемый пост)
Проверьте пожалуйста, ход рассуждений (только это, переписывать ничего не надо в коде!):
1. Примерно так.
2. Если введённое значение не подходит, то в очереди потока в cin, выставляется флаг, имеющий значение "ложь", что даёт запуск цикла "while". (истина = не-ложь)
3. Цикл "while (!cin)" операторами в теле цикла: cin.clear() очищает очередь символов , а while (cin.get()) выполняет сброс символа новой строки столько раз, пока они там есть. Continue выполняет новую и новую итерацию, пока там ещё есть символы новой строки. Сам cin.clear () не может выполнить очистку на символы новой строки.
4. Производится считывание временной переменной "value", если оно истинно, т.е. введено корректное значение (число), то флаг в условии цикла while (!cin) равен "истина".
5. Число присваивается элементу массива. При наличии корректного ввода, происходит выполнение цикла for (), без циклов while()  


1. Не совсем ввод, это считывание из потока, связанного с консолью.
2. Значения из потока извлекаются вот этим оператором http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/. При неудачном чтении у объекта потока выставляются соответствующие флаги, в случае неподходящего значения failbit. У объекта потока есть свойство на основании флагов ошибок быть преобразованым к булевому значению. При выставленном failbit (в случае неудачного чтения), преобразование потока к bool даст false.
3. Здесь неправильно. cin.clear() по умолчанию сбрасывает флаги ошибок http://www.cplusplus.com/reference/ios/ios/clear/. Про символ новой строки было бы корректно сказать, что он его пропускает (извлекает из потока и игнорирует), а не сбрасывает. cin.clear() не умеет и не должен что-либо читать или извлекать из потока. Ошибки сбрасываются для того, чтобы произвести следующее чтение, т.к. если флаг ошибки останется, бессмысленно повторять чтение.
4. Нет. Если чтение прошло удачно - цикл повторять не нужно, (!cin) возвращает true в случае ошибки чтения, чтобы его повторить, если чтение прошло успешно  (!cin) венёть ложь (false) и выполнение цикла прекратится.
5. Да.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)