Стандартное состояние ввода после состояния ошибки

#c #iostream

Вопрос:

Следующий фрагмент кода взят из C Iostreams Handbook by Steve Teale . Он предлагает вызывать cin в бесконечном цикле, чтобы пользователю постоянно предлагался правильный ввод, и только когда вводится правильный ввод, мы выходим из цикла.

Этот фрагмент кода работает правильно, но меня смущает if(cin){...} утверждение. Я бы ожидал чего-то подобного if(!cin.fail()){...} .

 #include <limits.h>
#include <iostream>
using namespace std;

int main()
{
  int n;
  cin.unsetf(ios::skipws);
  // turn off whitespece skipping
  
  cout << "Enter a value for n, followed by [Enter]: " << flush;
  
  for(;;) {
    cin >> n;
    if(cin) { //cin is in good state; input was ok
      cin.ignore(INT_MAX, 'n');
                // flush away the unwanted
                // newline character
      break;
    }

    // Poster's comment (not from the author)
    // In this section of the code cin has evaluated to false
    //
    cin.clear(); // clear the error state
    cin.ignore(INT_MAX, 'n');
                 // get rid of garbage characters
    cout << "That was no good, try again: " << flush;
  }

  return 0;
}
 

В) Как cin вычисляет значение false (т.Е. нулевое или нулевое значение) в случае сбоя?

cin — это объект, а не указатель, для которого можно установить значение null. Кроме того, в разделе кода, где cin принимает значение false, мы все еще можем вызывать функции-члены, такие как clear and ignore .

Комментарии:

1. Они только что изменили логику. Цикл представляет собой непрерывный цикл чтения, который прерывается только при получении правильных входных данных. Это прекрасный способ сделать это. Примечание: cin.ignore(INT_MAX, 'n'); очистка после правильного ввода в случае, если после чтения целого числа были какие-либо посторонние символы n , например "4 and other stuff" . Что также является хорошей практикой.

2. @DavidC.Rankin как cin принимает значение False? Пожалуйста, пролейте некоторый свет на это.

3. Каждый раз, когда возникает ошибка (например badbit , или failbit установлено), состояние потока будет оценивать false , проверяете ли вы if (cin) или if (cin.good()) . В обоих случаях, если установлен бит ошибки, условие равно false .

4. @DavidC.Rankin есть ли какая-то магия перегрузки оператора, которая позволяет использовать cin в логическом контексте (в if инструкции)? Кажется, что-то большее, чем кажется на первый взгляд. Пожалуйста, укажите мне на какую-нибудь ссылку, и я соответствующим образом просветлю себя.

5. См. std::basic_ios::operator bool и std ::ios_base::iostate . Он будет проверяться true на goodbit or eofbit , false иначе.

Ответ №1:

То, что вы наблюдаете, является результатом наследования и неявного преобразования. Более конкретно, std::cin имеет operator bool() функцию, которая преобразует состояние потока в логическое значение, и этот оператор возвращает !fail() .

std::cin является глобальным std::basic_istream , предоставляемым стандартной библиотекой, и basic_istream наследуется от std::basic_ios которой определяет функцию operator bool()

Цепочка наследования:

 std::ios_base <-- std::basic_ios <-- std::basic_istream
 

Вы можете найти таблицу внизу этой веб-страницы полезной для сравнения operator bool() с другими функциями проверки состояния потока и различными флагами состояния потоков.